Merge branch '单边仓位_master' of http://120.25.162.35:82/hucan/exchange_go into 单边仓位_master
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
@ -33,7 +34,7 @@ func (e LineApiGroup) GetPage(c *gin.Context) {
|
||||
s := service.LineApiGroup{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
|
||||
@ -33,7 +33,7 @@ func (e LineApiUser) GetPage(c *gin.Context) {
|
||||
s := service.LineApiUser{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form, nil).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
@ -32,7 +33,7 @@ func (e LineCoinnetwork) GetPage(c *gin.Context) {
|
||||
s := service.LineCoinnetwork{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
@ -84,7 +85,7 @@ func (e LineCoinnetwork) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建【币种网络】
|
||||
@ -154,7 +155,7 @@ func (e LineCoinnetwork) Update(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("修改【币种网络】失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除【币种网络】
|
||||
@ -187,5 +188,5 @@ func (e LineCoinnetwork) Delete(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("删除【币种网络】失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
@ -113,11 +113,7 @@ func (e LinePreOrder) GetChildOrderList(c *gin.Context) {
|
||||
}
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
list := make([]models.LinePreOrder, 0)
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.GetChildList(&req, p, &list)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("获取子订单信息失败,\r\n失败信息 %s", err.Error()))
|
||||
@ -310,6 +306,35 @@ func (e LinePreOrder) AddPreOrder(c *gin.Context) {
|
||||
e.OK(nil, "操作成功")
|
||||
}
|
||||
|
||||
// // 手动加仓
|
||||
// func (e LinePreOrder) AddPosition(c *gin.Context) {
|
||||
// s := service.LinePreOrder{}
|
||||
// req := dto.LinePreOrderAddPositionReq{}
|
||||
// err := e.MakeContext(c).
|
||||
// MakeOrm().
|
||||
// Bind(&req).
|
||||
// MakeService(&s.Service).
|
||||
// Errors
|
||||
// if err != nil {
|
||||
// e.Logger.Error(err)
|
||||
// e.Error(500, err, err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// if err := req.Valid(); err != nil {
|
||||
// e.Error(500, err, err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// err = s.AddPosition(&req)
|
||||
|
||||
// if err != nil {
|
||||
// e.Error(500, nil, err.Error())
|
||||
// return
|
||||
// }
|
||||
// e.OK(nil, "操作成功")
|
||||
// }
|
||||
|
||||
// BatchAddOrder 批量添加
|
||||
func (e LinePreOrder) BatchAddOrder(c *gin.Context) {
|
||||
s := service.LinePreOrder{}
|
||||
@ -629,8 +654,7 @@ func (e LinePreOrder) CalculateBreakEevenRatio(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// data := dto.CalculateBreakEvenRatioResp{}
|
||||
_, err = s.GenerateOrder(&req)
|
||||
err = s.GenerateOrder(&req)
|
||||
if err != nil {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
@ -34,7 +35,7 @@ func (e LineSymbolBlack) GetPage(c *gin.Context) {
|
||||
s := service.LineSymbolBlack{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
@ -86,7 +87,7 @@ func (e LineSymbolBlack) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建交易对黑名单
|
||||
@ -156,7 +157,7 @@ func (e LineSymbolBlack) Update(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("修改交易对黑名单失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除交易对黑名单
|
||||
@ -189,5 +190,33 @@ func (e LineSymbolBlack) Delete(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("删除交易对黑名单失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
// 重置交易对
|
||||
func (e LineSymbolBlack) RelodSymbol(c *gin.Context) {
|
||||
s := service.LineSymbolBlack{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.ReloadSymbol("1")
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("重置现货交易对失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
err = s.ReloadSymbol("2")
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("重置合约交易对失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "重置成功")
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
statuscode "go-admin/common/status_code"
|
||||
)
|
||||
|
||||
type LineUser struct {
|
||||
@ -32,7 +34,7 @@ func (e LineUser) GetPage(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
@ -84,7 +86,7 @@ func (e LineUser) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建会员表
|
||||
@ -154,7 +156,7 @@ func (e LineUser) Update(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("修改会员表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除会员表
|
||||
@ -187,5 +189,36 @@ func (e LineUser) Delete(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("删除会员表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
// 重新获取资产
|
||||
func (e LineUser) ReloadProperty(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
req := dto.LineUserReloadPropertyReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data := dto.LineUserPropertyResp{}
|
||||
code := s.GetProperty(req.UserId, &data)
|
||||
|
||||
if code != statuscode.OK {
|
||||
if code == statuscode.UserApiUserNotBind {
|
||||
e.Error(500, nil, "用户未绑定api")
|
||||
} else {
|
||||
e.Error(500, nil, "获取失败")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "操作成功")
|
||||
}
|
||||
|
||||
191
app/admin/apis/line_user_setting.go
Normal file
191
app/admin/apis/line_user_setting.go
Normal file
@ -0,0 +1,191 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
)
|
||||
|
||||
type LineUserSetting struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// GetPage 获取用户资产、配置表列表
|
||||
// @Summary 获取用户资产、配置表列表
|
||||
// @Description 获取用户资产、配置表列表
|
||||
// @Tags 用户资产、配置表
|
||||
// @Param pageSize query int false "页条数"
|
||||
// @Param pageIndex query int false "页码"
|
||||
// @Success 200 {object} response.Response{data=response.Page{list=[]models.LineUserSetting}} "{"code": 200, "data": [...]}"
|
||||
// @Router /api/v1/line-user-setting [get]
|
||||
// @Security Bearer
|
||||
func (e LineUserSetting) GetPage(c *gin.Context) {
|
||||
req := dto.LineUserSettingGetPageReq{}
|
||||
s := service.LineUserSetting{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
list := make([]models.LineUserSetting, 0)
|
||||
var count int64
|
||||
|
||||
err = s.GetPage(&req, p, &list, &count)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("获取用户资产、配置表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||
}
|
||||
|
||||
// Get 获取用户资产、配置表
|
||||
// @Summary 获取用户资产、配置表
|
||||
// @Description 获取用户资产、配置表
|
||||
// @Tags 用户资产、配置表
|
||||
// @Param id path int false "id"
|
||||
// @Success 200 {object} response.Response{data=models.LineUserSetting} "{"code": 200, "data": [...]}"
|
||||
// @Router /api/v1/line-user-setting/{id} [get]
|
||||
// @Security Bearer
|
||||
func (e LineUserSetting) Get(c *gin.Context) {
|
||||
req := dto.LineUserSettingGetReq{}
|
||||
s := service.LineUserSetting{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
var object models.LineUserSetting
|
||||
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
err = s.Get(&req, p, &object)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("获取用户资产、配置表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建用户资产、配置表
|
||||
// @Summary 创建用户资产、配置表
|
||||
// @Description 创建用户资产、配置表
|
||||
// @Tags 用户资产、配置表
|
||||
// @Accept application/json
|
||||
// @Product application/json
|
||||
// @Param data body dto.LineUserSettingInsertReq true "data"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
|
||||
// @Router /api/v1/line-user-setting [post]
|
||||
// @Security Bearer
|
||||
func (e LineUserSetting) Insert(c *gin.Context) {
|
||||
req := dto.LineUserSettingInsertReq{}
|
||||
s := service.LineUserSetting{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
// 设置创建人
|
||||
req.SetCreateBy(user.GetUserId(c))
|
||||
|
||||
err = s.Insert(&req)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("创建用户资产、配置表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(req.GetId(), "创建成功")
|
||||
}
|
||||
|
||||
// Update 修改用户资产、配置表
|
||||
// @Summary 修改用户资产、配置表
|
||||
// @Description 修改用户资产、配置表
|
||||
// @Tags 用户资产、配置表
|
||||
// @Accept application/json
|
||||
// @Product application/json
|
||||
// @Param id path int true "id"
|
||||
// @Param data body dto.LineUserSettingUpdateReq true "body"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||
// @Router /api/v1/line-user-setting/{id} [put]
|
||||
// @Security Bearer
|
||||
func (e LineUserSetting) Update(c *gin.Context) {
|
||||
req := dto.LineUserSettingUpdateReq{}
|
||||
s := service.LineUserSetting{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
req.SetUpdateBy(user.GetUserId(c))
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
|
||||
err = s.Update(&req, p)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("修改用户资产、配置表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除用户资产、配置表
|
||||
// @Summary 删除用户资产、配置表
|
||||
// @Description 删除用户资产、配置表
|
||||
// @Tags 用户资产、配置表
|
||||
// @Param data body dto.LineUserSettingDeleteReq true "body"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
|
||||
// @Router /api/v1/line-user-setting [delete]
|
||||
// @Security Bearer
|
||||
func (e LineUserSetting) Delete(c *gin.Context) {
|
||||
s := service.LineUserSetting{}
|
||||
req := dto.LineUserSettingDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// req.SetUpdateBy(user.GetUserId(c))
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
|
||||
err = s.Remove(&req, p)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("删除用户资产、配置表失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
}
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
@ -32,7 +33,7 @@ func (e MemberRenwaLog) GetPage(c *gin.Context) {
|
||||
s := service.MemberRenwaLog{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
@ -84,7 +85,7 @@ func (e MemberRenwaLog) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建会员续期记录
|
||||
@ -154,7 +155,7 @@ func (e MemberRenwaLog) Update(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("修改会员续期记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除会员续期记录
|
||||
@ -187,5 +188,5 @@ func (e MemberRenwaLog) Delete(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("删除会员续期记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ func (e MemberRenwalConfig) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
e.OK( object, "查询成功")
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建会员套餐管理
|
||||
@ -112,6 +112,12 @@ func (e MemberRenwalConfig) Insert(c *gin.Context) {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := req.Valid(); err != nil {
|
||||
e.Error(500, err, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 设置创建人
|
||||
req.SetCreateBy(user.GetUserId(c))
|
||||
|
||||
@ -148,6 +154,12 @@ func (e MemberRenwalConfig) Update(c *gin.Context) {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := req.Valid(); err != nil {
|
||||
e.Error(500, err, "")
|
||||
return
|
||||
}
|
||||
|
||||
req.SetUpdateBy(user.GetUserId(c))
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
|
||||
@ -156,7 +168,7 @@ func (e MemberRenwalConfig) Update(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("修改会员套餐管理失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "修改成功")
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除会员套餐管理
|
||||
@ -189,5 +201,5 @@ func (e MemberRenwalConfig) Delete(c *gin.Context) {
|
||||
e.Error(500, err, fmt.Sprintf("删除会员套餐管理失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK( req.GetId(), "删除成功")
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
241
app/admin/apis/member_withdrawal_log.go
Normal file
241
app/admin/apis/member_withdrawal_log.go
Normal file
@ -0,0 +1,241 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLog struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// GetPage 获取用户提现记录列表
|
||||
// @Summary 获取用户提现记录列表
|
||||
// @Description 获取用户提现记录列表
|
||||
// @Tags 用户提现记录
|
||||
// @Param networkName query string false "网络名称"
|
||||
// @Param status query string false "提现状态(member_withdrawal_status)"
|
||||
// @Param pageSize query int false "页条数"
|
||||
// @Param pageIndex query int false "页码"
|
||||
// @Success 200 {object} response.Response{data=response.Page{list=[]models.MemberWithdrawalLog}} "{"code": 200, "data": [...]}"
|
||||
// @Router /api/v1/member-withdrawal-log [get]
|
||||
// @Security Bearer
|
||||
func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
|
||||
req := dto.MemberWithdrawalLogGetPageReq{}
|
||||
s := service.MemberWithdrawalLog{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
list := make([]models.MemberWithdrawalLog, 0)
|
||||
var count int64
|
||||
|
||||
err = s.GetPage(&req, p, &list, &count)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("获取用户提现记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||
}
|
||||
|
||||
// Get 获取用户提现记录
|
||||
// @Summary 获取用户提现记录
|
||||
// @Description 获取用户提现记录
|
||||
// @Tags 用户提现记录
|
||||
// @Param id path int false "id"
|
||||
// @Success 200 {object} response.Response{data=models.MemberWithdrawalLog} "{"code": 200, "data": [...]}"
|
||||
// @Router /api/v1/member-withdrawal-log/{id} [get]
|
||||
// @Security Bearer
|
||||
func (e MemberWithdrawalLog) Get(c *gin.Context) {
|
||||
req := dto.MemberWithdrawalLogGetReq{}
|
||||
s := service.MemberWithdrawalLog{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
var object models.MemberWithdrawalLog
|
||||
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
err = s.Get(&req, p, &object)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("获取用户提现记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(object, "查询成功")
|
||||
}
|
||||
|
||||
// Insert 创建用户提现记录
|
||||
// @Summary 创建用户提现记录
|
||||
// @Description 创建用户提现记录
|
||||
// @Tags 用户提现记录
|
||||
// @Accept application/json
|
||||
// @Product application/json
|
||||
// @Param data body dto.MemberWithdrawalLogInsertReq true "data"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
|
||||
// @Router /api/v1/member-withdrawal-log [post]
|
||||
// @Security Bearer
|
||||
func (e MemberWithdrawalLog) Insert(c *gin.Context) {
|
||||
req := dto.MemberWithdrawalLogInsertReq{}
|
||||
s := service.MemberWithdrawalLog{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
// 设置创建人
|
||||
req.SetCreateBy(user.GetUserId(c))
|
||||
|
||||
err = s.Insert(&req)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("创建用户提现记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(req.GetId(), "创建成功")
|
||||
}
|
||||
|
||||
// Update 修改用户提现记录
|
||||
// @Summary 修改用户提现记录
|
||||
// @Description 修改用户提现记录
|
||||
// @Tags 用户提现记录
|
||||
// @Accept application/json
|
||||
// @Product application/json
|
||||
// @Param id path int true "id"
|
||||
// @Param data body dto.MemberWithdrawalLogUpdateReq true "body"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||
// @Router /api/v1/member-withdrawal-log/{id} [put]
|
||||
// @Security Bearer
|
||||
func (e MemberWithdrawalLog) Update(c *gin.Context) {
|
||||
req := dto.MemberWithdrawalLogUpdateReq{}
|
||||
s := service.MemberWithdrawalLog{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
req.SetUpdateBy(user.GetUserId(c))
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
|
||||
err = s.Update(&req, p)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("修改用户提现记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "修改成功")
|
||||
}
|
||||
|
||||
// Delete 删除用户提现记录
|
||||
// @Summary 删除用户提现记录
|
||||
// @Description 删除用户提现记录
|
||||
// @Tags 用户提现记录
|
||||
// @Param data body dto.MemberWithdrawalLogDeleteReq true "body"
|
||||
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
|
||||
// @Router /api/v1/member-withdrawal-log [delete]
|
||||
// @Security Bearer
|
||||
func (e MemberWithdrawalLog) Delete(c *gin.Context) {
|
||||
s := service.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogDeleteReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// req.SetUpdateBy(user.GetUserId(c))
|
||||
p := actions.GetPermissionFromContext(c)
|
||||
|
||||
err = s.Remove(&req, p)
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("删除用户提现记录失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(req.GetId(), "删除成功")
|
||||
}
|
||||
|
||||
// 审核提现
|
||||
func (e MemberWithdrawalLog) Process(c *gin.Context) {
|
||||
s := service.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogApprovedReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.Process(&req)
|
||||
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("审核提现失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(nil, "确认提现成功")
|
||||
}
|
||||
|
||||
// 确认提现
|
||||
func (e MemberWithdrawalLog) Confirm(c *gin.Context) {
|
||||
s := service.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogConfirmReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.Confirm(&req)
|
||||
|
||||
if err != nil {
|
||||
e.Error(500, err, fmt.Sprintf("确认到账失败,\r\n失败信息 %s", err.Error()))
|
||||
return
|
||||
}
|
||||
e.OK(nil, "确认提现成功")
|
||||
}
|
||||
@ -76,7 +76,7 @@ func (e SysDictData) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var object models.SysDictData
|
||||
var object dto.SysDictDataResp
|
||||
|
||||
err = s.Get(&req, &object)
|
||||
if err != nil {
|
||||
|
||||
37
app/admin/fronted/common.go
Normal file
37
app/admin/fronted/common.go
Normal file
@ -0,0 +1,37 @@
|
||||
package fronted
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/common/service/sysservice/sysstatuscode"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
)
|
||||
|
||||
type Common struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// 获取默认设置
|
||||
func (e Common) GetDefaultSet(c *gin.Context) {
|
||||
s := appservice.Common{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
|
||||
return
|
||||
}
|
||||
|
||||
data, code := s.GetDefaultSet()
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(data, "success")
|
||||
}
|
||||
46
app/admin/fronted/invite_log.go
Normal file
46
app/admin/fronted/invite_log.go
Normal file
@ -0,0 +1,46 @@
|
||||
package fronted
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/common"
|
||||
"go-admin/app/admin/service/dto"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
)
|
||||
|
||||
type InviteLog struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// GetPage 获取InviteLog列表
|
||||
func (e InviteLog) GetPersonnalPage(c *gin.Context) {
|
||||
s := appservice.InviteLog{}
|
||||
req := dto.PersonnalInviteLogPageReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
datas := make([]dto.InviteLogResp, 0)
|
||||
req.UserId = common.GetUserId(c)
|
||||
|
||||
if req.UserId == 0 {
|
||||
req.UserId = -1
|
||||
}
|
||||
var count int64
|
||||
err = s.GetPage(&req, &datas, &count)
|
||||
|
||||
if err != nil {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
e.PageOK(datas, int(count), req.PageIndex, req.PageSize, "success")
|
||||
}
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"go-admin/app/admin/models/sysmodel"
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/aduserdb"
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/common"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/const/rediskey"
|
||||
@ -23,6 +24,7 @@ import (
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
@ -35,11 +37,15 @@ type LineUserApi struct {
|
||||
// Register 用户注册
|
||||
func (e LineUserApi) Register(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
userAppService := appservice.LineUser{}
|
||||
balanceService := service.MemberBalance{}
|
||||
req := sysmodel.FrontedUserRegisterReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
MakeService(&userAppService.Service).
|
||||
MakeService(&balanceService.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
@ -66,6 +72,10 @@ func (e LineUserApi) Register(c *gin.Context) {
|
||||
e.Error(ok, nil, sysstatuscode.GetStatusCodeDescription(c, ok))
|
||||
return
|
||||
}
|
||||
|
||||
userAppService.SetDefaultRenwal(user)
|
||||
balanceService.CreateDefaultBalance(user)
|
||||
|
||||
resp := map[string]interface{}{
|
||||
"email": req.Email,
|
||||
"mobile": req.Phone,
|
||||
@ -109,7 +119,7 @@ func (e LineUserApi) VerifyEmail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
// 核验邮箱验证码
|
||||
code := authservice.UserVerifyEmail(req.Email, req.VerifyCode, e.Orm)
|
||||
code := authservice.UserVerifyEmail(req.Email, req.VerifyCode, 0, e.Orm)
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
@ -123,7 +133,7 @@ func (e LineUserApi) VerifyEmail(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
// SendVerifyEmail 发送注册校验邮箱
|
||||
// SendVerifyEmail 发送邮箱
|
||||
func (e LineUserApi) SendVerifyEmail(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
req := dto.FrontedSendVerifyEmailReq{}
|
||||
@ -144,7 +154,8 @@ func (e LineUserApi) SendVerifyEmail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
emailCode := inttostring.GenerateRandomString(10)
|
||||
code = authservice.SendRegisterEmail(req.Email, emailCode)
|
||||
language := common.GetLanguage(c)
|
||||
code = authservice.SendRegisterEmail(req.Email, emailCode, req.Type, language)
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
@ -173,13 +184,15 @@ func (e LineUserApi) SendRegisterSms(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if req.Type == 0 {
|
||||
user, _ := aduserdb.GetUserByPhone(e.Orm, req.PhoneAreaCode, req.Phone)
|
||||
if user.Id > 0 {
|
||||
e.Error(statuscode.TheAccountIsAlreadyRegistered, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.TheAccountIsAlreadyRegistered))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
code = authservice.SendGoToneSms(req.Phone, req.PhoneAreaCode)
|
||||
code = authservice.SendGoToneSms(req.Phone, req.PhoneAreaCode, req.Type)
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
@ -336,9 +349,11 @@ func (e LineUserApi) GetWhiteIp(c *gin.Context) {
|
||||
// Info 用户中心
|
||||
func (e LineUserApi) Info(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
balance := service.MemberBalance{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
MakeService(&s.Service).
|
||||
MakeService(&balance.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
@ -394,11 +409,15 @@ func (e LineUserApi) Info(c *gin.Context) {
|
||||
fundingAsset = resp[0:]
|
||||
}
|
||||
|
||||
balanceData, _ := balance.GetBalance(userId)
|
||||
|
||||
//获取盈利情况
|
||||
logs := service.LineUserProfitLogs{Service: s.Service}
|
||||
totalProfit, todayProfit := logs.GetProfitInfoByUserId(userinfo.Id)
|
||||
user := map[string]interface{}{
|
||||
"avatar": userinfo.Avatar,
|
||||
"user_id": userinfo.Id,
|
||||
"user_name": userinfo.Nickname,
|
||||
"invite_num": userinfo.RecommendNum,
|
||||
"open_status": apiUserinfo.OpenStatus,
|
||||
"is_auth": isAuth,
|
||||
@ -415,6 +434,11 @@ func (e LineUserApi) Info(c *gin.Context) {
|
||||
"funding_asset": fundingAsset,
|
||||
"total_profit": totalProfit.Float64,
|
||||
"today_profit": todayProfit.Float64,
|
||||
"balance": map[string]interface{}{ //系统余额
|
||||
"total_amount": balanceData.TotalAmount,
|
||||
"free_amount": balanceData.FreeAmount,
|
||||
"frozen_amount": balanceData.FrozenAmount,
|
||||
},
|
||||
}
|
||||
e.OK(returnMap, "success")
|
||||
|
||||
@ -435,16 +459,10 @@ func (e LineUserApi) OpenStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
userId := common.GetUserId(c)
|
||||
var apiUser models.LineApiUser
|
||||
err = e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", userId).Find(&apiUser).Error
|
||||
code := s.OpenStatus(&req, userId)
|
||||
|
||||
if apiUser.ApiSecret == "" || apiUser.ApiKey == "" {
|
||||
e.Error(statuscode.UserApiKeyRequired, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.UserApiKeyRequired))
|
||||
return
|
||||
}
|
||||
err = e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", userId).Update("open_status", req.Status).Error
|
||||
if err != nil {
|
||||
e.Error(500, err, err.Error())
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
e.OK(nil, "success")
|
||||
@ -579,3 +597,128 @@ func (e LineUserApi) CallBack(c *gin.Context) {
|
||||
|
||||
e.OK(nil, "")
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
func (e LineUserApi) Logout(c *gin.Context) {
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userId := common.GetUserId(c)
|
||||
err = authservice.Logout(userId, 1)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("退出登录失败:", err.Error())
|
||||
e.Error(statuscode.ServerError, nil, "")
|
||||
}
|
||||
|
||||
e.OK(nil, "success")
|
||||
}
|
||||
|
||||
// 查询个人资产
|
||||
func (e LineUserApi) GetProperty(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
|
||||
}
|
||||
|
||||
var data dto.LineUserPropertyResp
|
||||
userId := common.GetUserId(c)
|
||||
code := s.GetProperty(userId, &data)
|
||||
if code != statuscode.OK && code != statuscode.UserApiUserNotBind {
|
||||
// e.Logger.Error(err)
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(data, "success")
|
||||
}
|
||||
|
||||
// 获取到期时间
|
||||
func (e LineUserApi) GetUserInfo(c *gin.Context) {
|
||||
s := appservice.LineUser{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
|
||||
}
|
||||
|
||||
userId := common.GetUserId(c)
|
||||
var data dto.LineUserAppResp
|
||||
code := s.GetUserInfo(userId, &data)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(data, "success")
|
||||
}
|
||||
|
||||
// 用户下单设置
|
||||
func (e LineUserApi) UserOrderSet(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
req := dto.LineUserOrderSetReq{}
|
||||
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
|
||||
}
|
||||
|
||||
userId := common.GetUserId(c)
|
||||
code := s.OrderSet(&req, userId)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "success")
|
||||
}
|
||||
|
||||
func (e LineUserApi) ResetPassword(c *gin.Context) {
|
||||
s := service.LineUser{}
|
||||
req := dto.LineUserResetPwdReq{}
|
||||
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
|
||||
}
|
||||
|
||||
if code := req.Valid(); code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
code := s.ResetPassword(&req)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "success")
|
||||
}
|
||||
|
||||
44
app/admin/fronted/member_balance_log.go
Normal file
44
app/admin/fronted/member_balance_log.go
Normal file
@ -0,0 +1,44 @@
|
||||
package fronted
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/common"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/service/sysservice/sysstatuscode"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
)
|
||||
|
||||
type MemberBalanceLog struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
func (e MemberBalanceLog) GetPage(c *gin.Context) {
|
||||
s := appservice.MemberBalanceLog{}
|
||||
req := dto.MemberBalanceLogPageAppReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, "server error")
|
||||
return
|
||||
}
|
||||
req.UserId = common.GetUserId(c)
|
||||
req.Language = common.GetLanguage(c)
|
||||
data := make([]dto.MemberBalanceLogAppResp, 0)
|
||||
var count int64
|
||||
code := s.GetPage(&req, &data, &count)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
}
|
||||
|
||||
e.PageOK(data, int(count), req.PageIndex, req.PageSize, "success")
|
||||
}
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"go-admin/app/admin/service/appservice"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"go-admin/common/service/common"
|
||||
"go-admin/common/service/sysservice/sysstatuscode"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -27,7 +28,9 @@ func (e MemberRenwalConfig) GetActiveList(c *gin.Context) {
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
data, code := s.GetList()
|
||||
|
||||
language := common.GetLanguage(c)
|
||||
data, code := s.GetList(language)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
)
|
||||
|
||||
@ -19,14 +20,51 @@ type MemberRenwalLog struct {
|
||||
func (e MemberRenwalLog) GetPage(c *gin.Context) {
|
||||
s := appservice.MemberRenwalLog{}
|
||||
req := dto.MemberRenwalLogPageAppReq{}
|
||||
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, "server error")
|
||||
return
|
||||
}
|
||||
userId := common.GetUserId(c)
|
||||
req.Language = common.GetLanguage(c)
|
||||
data := make([]dto.MemberRenwalLogResp, 0)
|
||||
code := s.GetPage(userId, &req, &data)
|
||||
var count int64
|
||||
code := s.GetPage(userId, &req, &data, &count)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
}
|
||||
|
||||
e.PageOK(data, int(count), req.PageIndex, req.PageSize, "success")
|
||||
}
|
||||
|
||||
func (e MemberRenwalLog) Apply(c *gin.Context) {
|
||||
s := appservice.MemberRenwalLog{}
|
||||
req := dto.MemberRenwalCreateAppReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, "server error")
|
||||
return
|
||||
}
|
||||
|
||||
req.UserId = common.GetUserId(c)
|
||||
data := dto.MemberRenwalCreateAppResp{}
|
||||
code := s.Renwal(&req, &data)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(data, "success")
|
||||
}
|
||||
|
||||
107
app/admin/fronted/member_withdrawal_log.go
Normal file
107
app/admin/fronted/member_withdrawal_log.go
Normal file
@ -0,0 +1,107 @@
|
||||
package fronted
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/common"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/service/sysservice/sysstatuscode"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLog struct {
|
||||
api.Api
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
|
||||
s := appservice.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogGetPageAppReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req, binding.Form, binding.Query).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var count int64
|
||||
var list []dto.MemberWithdrawalLogResp
|
||||
|
||||
req.UserId = common.GetUserId(c)
|
||||
code := s.GetPage(&req, &list, &count)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
}
|
||||
|
||||
e.PageOK(list, int(count), req.PageIndex, req.PageSize, "success")
|
||||
}
|
||||
|
||||
// 用户提现申请
|
||||
func (e MemberWithdrawalLog) Apply(c *gin.Context) {
|
||||
s := appservice.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogApplyReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if code := req.Valid(); code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
req.UserId = common.GetUserId(c)
|
||||
code := s.Apply(&req)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "success")
|
||||
}
|
||||
|
||||
// 用户取消提现
|
||||
func (e MemberWithdrawalLog) Cancel(c *gin.Context) {
|
||||
s := appservice.MemberWithdrawalLog{}
|
||||
req := dto.MemberWithdrawalLogCancelReq{}
|
||||
err := e.MakeContext(c).
|
||||
MakeOrm().
|
||||
Bind(&req).
|
||||
MakeService(&s.Service).
|
||||
Errors
|
||||
if err != nil {
|
||||
e.Logger.Error(err)
|
||||
e.Error(500, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if code := req.Valid(); code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
userId := common.GetUserId(c)
|
||||
code := s.Canceled(&req, userId)
|
||||
|
||||
if code != statuscode.OK {
|
||||
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
|
||||
return
|
||||
}
|
||||
|
||||
e.OK(nil, "success")
|
||||
}
|
||||
@ -16,6 +16,7 @@ type LineCoinnetwork struct {
|
||||
UnlockTime int64 `json:"unlockTime" gorm:"type:int;comment:提现确认平均时间,单位分钟"`
|
||||
Fee decimal.Decimal `json:"fee" gorm:"type:decimal(32,6);comment:网络手续费(百分比)"`
|
||||
MinWithdrawal decimal.Decimal `json:"minWithdrawal" gorm:"type:decimal(32,6);comment:最小提现金额"`
|
||||
Status int `json:"status" gorm:"type:int;comment:状态 1 启用 2 禁用"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
@ -11,20 +11,19 @@ type LinePreOrderExt struct {
|
||||
|
||||
MainOrderId int `json:"mainOrderId" gorm:"type:bigint;comment:主单id"`
|
||||
OrderId int `json:"orderId" gorm:"type:bigint;comment:订单id"`
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" gorm:"type:decimal(10,2);comment:止盈百分比"`
|
||||
ReTakeRatio decimal.Decimal `json:"reTakeRatio" gorm:"type:decimal(10,2);comment:亏损回本止盈百分比"`
|
||||
ReduceOrderType string `json:"reduceOrderType" gorm:"type:varchar(20);comment:减仓类型 LIMIT-限价 MARKET-市价"`
|
||||
ReducePriceRatio decimal.Decimal `json:"reducePriceRatio" gorm:"type:decimal(10,2);comment:减仓价格百分比"`
|
||||
ReduceNumRatio decimal.Decimal `json:"reduceNumRatio" gorm:"type:decimal(10,2);comment:减仓数量百分比"`
|
||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduceTakeProfitRatio" gorm:"type:decimal(10,2);comment:减仓后止盈百分比"`
|
||||
ReduceStopLossRatio decimal.Decimal `json:"reduceStopLossRatio" gorm:"type:decimal(10,2);comment:减仓后止损百分比"`
|
||||
AddPositionOrderType string `json:"addPositionOrderType" gorm:"type:varchar(20);comment:加仓类型 LIMIT-限价 MARKET-市价"`
|
||||
AddPositionPriceRatio decimal.Decimal `json:"addPositionPriceRatio" gorm:"type:decimal(10,2);comment:加仓价格百分比"`
|
||||
AddPositionType int `json:"addPositionType" gorm:"type:int;comment:加仓类型 1-百分比 2-实际金额"`
|
||||
AddType int `json:"addType" gorm:"type:tinyint;comment:类型 1-加仓 2-减仓"`
|
||||
OrderType string `json:"orderType" gorm:"type:varchar(20);comment:订单类型 LIMIT-限价 MARKET-市价"`
|
||||
PriceRatio decimal.Decimal `json:"priceRatio" gorm:"type:decimal(10,2);comment: (加仓/减仓)触发价格百分比"`
|
||||
AddPositionType int `json:"addPositionType" gorm:"type:int;comment:(加仓/减仓)类型 1-百分比 2-实际金额"`
|
||||
AddPositionVal decimal.Decimal `json:"addPositionVal" gorm:"type:decimal(10,2);comment:加仓值"`
|
||||
ReduceReTakeRatio decimal.Decimal `json:"reduceReTakeRatio" gorm:"type:decimal(10,2);comment:减仓后亏损回本止盈百分比"`
|
||||
TotalAfterAdding decimal.Decimal `json:"totalAfterAdding" gorm:"-"` //加仓后总数
|
||||
TotalAfterReducing decimal.Decimal `json:"totalAfterReducing" gorm:"-"` //减仓后总数
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" gorm:"type:decimal(10,2);comment:止盈百分比"`
|
||||
StopLossRatio decimal.Decimal `json:"stopLossRatio" gorm:"type:decimal(10,2);comment:止损百分比"`
|
||||
TakeProfitNumRatio decimal.Decimal `json:"takeProfitNumRatio" gorm:"type:decimal(10,2);comment:止盈数量百分比"`
|
||||
TpTpPriceRatio decimal.Decimal `json:"tpTpPriceRatio" gorm:"type:decimal(10,2);comment:止盈后止盈百分比"`
|
||||
TpSlPriceRatio decimal.Decimal `json:"tpSlPriceRatio" gorm:"type:decimal(10,2);comment:止盈后止损百分比"`
|
||||
ReTakeRatio decimal.Decimal `json:"reTakeRatio" gorm:"type:decimal(10,2);comment:亏损回本止盈百分比"`
|
||||
TotalBefore decimal.Decimal `gorm:"-" comment:"初始总数"`
|
||||
TotalAfter decimal.Decimal `gorm:"-" comment:"剩余总数"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ type LineUser struct {
|
||||
TopReferrerId int `json:"topReferrerId" gorm:"type:int unsigned;comment:父级推荐人ID"`
|
||||
Username string `json:"username" gorm:"type:varchar(32);comment:用户名"`
|
||||
Nickname string `json:"nickname" gorm:"type:varchar(50);comment:昵称"`
|
||||
Password string `json:"password" gorm:"type:varchar(32);comment:密码"`
|
||||
Password string `json:"password" gorm:"type:varchar(50);comment:密码"`
|
||||
Salt string `json:"salt" gorm:"type:varchar(30);comment:密码盐"`
|
||||
Email string `json:"email" gorm:"type:varchar(100);comment:电子邮箱"`
|
||||
Mobile string `json:"mobile" gorm:"type:varchar(11);comment:手机号"`
|
||||
@ -39,7 +39,12 @@ type LineUser struct {
|
||||
Status string `json:"status" gorm:"type:varchar(30);comment:状态"`
|
||||
Verification string `json:"verification" gorm:"type:varchar(255);comment:验证"`
|
||||
LoginTime time.Time `json:"loginTime" gorm:"type:timestamp;comment:登录时间"`
|
||||
ExpirationTime *time.Time `json:"expirationTime" gorm:"type:timestamp;comment:过期时间"`
|
||||
OpenStatus int `json:"open_status" gorm:"-"`
|
||||
SpotFreeAmount decimal.Decimal `json:"spotFreeAmount" gorm:"-"`
|
||||
FutureFreeAmount decimal.Decimal `json:"futureFreeAmount" gorm:"-"`
|
||||
AssetUpdateTime *time.Time `json:"assetUpdateTime" gorm:"-"`
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount" gorm:"-"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
34
app/admin/models/line_user_setting.go
Normal file
34
app/admin/models/line_user_setting.go
Normal file
@ -0,0 +1,34 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type LineUserSetting struct {
|
||||
models.Model
|
||||
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户ID"`
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount" gorm:"type:decimal(32,8);comment:单笔最小金额"`
|
||||
SpotUsdtFreeAmount decimal.Decimal `json:"spotUsdtFreeAmount" gorm:"type:decimal(32,8);comment:现货USDT可用余额"`
|
||||
FutureUsdtFreeAmount decimal.Decimal `json:"futureUsdtFreeAmount" gorm:"type:decimal(32,8);comment:合约USDT可用余额"`
|
||||
AssetUpdateTime *time.Time `json:"assetUpdateTime" gorm:"type:datetime;comment:资产更新时间"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
func (LineUserSetting) TableName() string {
|
||||
return "line_user_setting"
|
||||
}
|
||||
|
||||
func (e *LineUserSetting) Generate() models.ActiveRecord {
|
||||
o := *e
|
||||
return &o
|
||||
}
|
||||
|
||||
func (e *LineUserSetting) GetId() interface{} {
|
||||
return e.Id
|
||||
}
|
||||
@ -9,7 +9,8 @@ import (
|
||||
type MemberBalance struct {
|
||||
models.Model
|
||||
|
||||
TotalAmont decimal.Decimal `json:"totalAmont" gorm:"type:decimal(18,6);comment:总余额"`
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
|
||||
TotalAmount decimal.Decimal `json:"totalAmount" gorm:"type:decimal(18,6);comment:总余额"`
|
||||
FreeAmount decimal.Decimal `json:"freeAmount" gorm:"type:decimal(18,6);comment:可用余额"`
|
||||
FrozenAmount decimal.Decimal `json:"frozenAmount" gorm:"type:decimal(18,6);comment:冻结金额"`
|
||||
models.ModelTime
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
|
||||
"go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberBalanceLog struct {
|
||||
@ -11,10 +11,10 @@ type MemberBalanceLog struct {
|
||||
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
|
||||
ChangeSource string `json:"changeSource" gorm:"type:varchar(50);comment:变更来源 (member_change_source)"`
|
||||
ChangeType string `json:"changeType" gorm:"type:tinyint;comment:变更类别 1-收入 2-支出"`
|
||||
Amount string `json:"amount" gorm:"type:decimal(18,6);comment:变更金额"`
|
||||
BalanceBefore string `json:"balanceBefore" gorm:"type:decimal(18,6);comment:变更前余额"`
|
||||
BalanceAfter string `json:"balanceAfter" gorm:"type:decimal(18,6);comment:变更后余额"`
|
||||
ChangeType int `json:"changeType" gorm:"type:tinyint;comment:变更类别 1-收入 2-支出"`
|
||||
Amount decimal.Decimal `json:"amount" gorm:"type:decimal(18,6);comment:变更金额"`
|
||||
BalanceBefore decimal.Decimal `json:"balanceBefore" gorm:"type:decimal(18,6);comment:变更前余额"`
|
||||
BalanceAfter decimal.Decimal `json:"balanceAfter" gorm:"type:decimal(18,6);comment:变更后余额"`
|
||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
|
||||
@ -5,20 +5,27 @@ import (
|
||||
|
||||
"go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberRenwaLog struct {
|
||||
models.Model
|
||||
|
||||
RenwalId string `json:"renwalId" gorm:"type:bigint;comment:套餐id"`
|
||||
NetworkName string `json:"networkName" gorm:"type:varchar(255);comment:网络名称"`
|
||||
ReceiveAddress string `json:"receiveAddress" gorm:"type:varchar(255);comment:接收地址"`
|
||||
RenwalId int `json:"renwalId" gorm:"type:bigint;comment:套餐id"`
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
|
||||
RenwalName string `json:"renwalName" gorm:"type:varchar(255);comment:续期套餐名称"`
|
||||
RenwalDuration string `json:"renwalDuration" gorm:"type:int;comment:续期时长(天数)"`
|
||||
RenwalDuration int `json:"renwalDuration" gorm:"type:int;comment:续期时长(天数)"`
|
||||
Status string `json:"status" gorm:"type:varchar(255);comment:订单状态(member_renwal_log_status)"`
|
||||
PayableAmount string `json:"payableAmount" gorm:"type:decimal(18,6);comment:应付金额"`
|
||||
ActualPaymentAmount string `json:"actualPaymentAmount" gorm:"type:decimal(18,6);comment:实付金额"`
|
||||
PayableAmount decimal.Decimal `json:"payableAmount" gorm:"type:decimal(18,6);comment:应付金额"`
|
||||
ActualPaymentAmount decimal.Decimal `json:"actualPaymentAmount" gorm:"type:decimal(18,6);comment:实付金额"`
|
||||
FromAddress string `json:"fromAddress" gorm:"type:varchar(255);comment:付款地址"`
|
||||
Coin string `json:"coin" gorm:"type:varchar(255);comment:代币"`
|
||||
PaymentTime time.Time `json:"paymentTime" gorm:"type:datetime;comment:支付时间"`
|
||||
PaymentTime *time.Time `json:"paymentTime" gorm:"type:datetime;comment:支付时间"`
|
||||
Hash string `json:"hash" gorm:"type:varchar(255);comment:交易hash"`
|
||||
ExpirationTime time.Time `json:"expirationTime" gorm:"type:datetime;comment:到期时间"`
|
||||
NickName string `json:"nickName" gorm:"-"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ type MemberRenwalConfig struct {
|
||||
models.Model
|
||||
|
||||
PackageName string `json:"packageName" gorm:"type:varchar(255);comment:套餐名称"`
|
||||
PackageNameEn string `json:"packageNameEn" gorm:"type:varchar(255);comment:套餐英文名称"`
|
||||
DurationDay int `json:"durationDay" gorm:"type:int;comment:续期时间(天)"`
|
||||
OriginalPrice decimal.Decimal `json:"originalPrice" gorm:"type:decimal(18,6);comment:原始单价"`
|
||||
DiscountPrice decimal.Decimal `json:"discountPrice" gorm:"type:decimal(18,6);comment:折扣价格 -1为未设置"`
|
||||
|
||||
42
app/admin/models/member_withdrawal_log.go
Normal file
42
app/admin/models/member_withdrawal_log.go
Normal file
@ -0,0 +1,42 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLog struct {
|
||||
models.Model
|
||||
|
||||
NetworkId int `json:"networkId" gorm:"type:int;comment:网络id"`
|
||||
NetworkName string `json:"networkName" gorm:"type:varchar(50);comment:网络名称"`
|
||||
Coin string `json:"coin" gorm:"type:varchar(50);comment:提现币种"`
|
||||
ToAddress string `json:"toAddress" gorm:"type:varchar(255);comment:提现地址"`
|
||||
Hash string `json:"hash" gorm:"type:varchar(255);comment:提现hash"`
|
||||
UserId int `json:"userId" gorm:"type:bigint;comment:用户id"`
|
||||
Amount decimal.Decimal `json:"amount" gorm:"type:decimal(32,6);comment:提现金额(U)"`
|
||||
Status string `json:"status" gorm:"type:varchar(20);comment:提现状态(member_withdrawal_status)"`
|
||||
ConfirmTime *time.Time `json:"confirmTime" gorm:"type:datetime;comment:确认时间"`
|
||||
Fee decimal.Decimal `json:"fee" gorm:"type:decimal(10,2);comment:手续费比例"`
|
||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
||||
UserName string `json:"userName" gorm:"-"`
|
||||
NickName string `json:"nickName" gorm:"-"`
|
||||
models.ModelTime
|
||||
models.ControlBy
|
||||
}
|
||||
|
||||
func (MemberWithdrawalLog) TableName() string {
|
||||
return "member_withdrawal_log"
|
||||
}
|
||||
|
||||
func (e *MemberWithdrawalLog) Generate() models.ActiveRecord {
|
||||
o := *e
|
||||
return &o
|
||||
}
|
||||
|
||||
func (e *MemberWithdrawalLog) GetId() interface{} {
|
||||
return e.Id
|
||||
}
|
||||
@ -16,6 +16,7 @@ type SysDictData struct {
|
||||
Status int `json:"status" gorm:"size:4;comment:Status"`
|
||||
Default string `json:"default" gorm:"size:8;comment:Default"`
|
||||
Remark string `json:"remark" gorm:"size:255;comment:Remark"`
|
||||
Language string `json:"language" gorm:"type:text;comment:多语言(json)"`
|
||||
models.ControlBy
|
||||
models.ModelTime
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ type FrontedUserRegisterReq struct {
|
||||
InviteCode string `json:"invite_code"` // 邀请码
|
||||
IP string `json:"-"` // IP
|
||||
Pid int `json:"-"` // 推荐人ID
|
||||
|
||||
Language string `json:"-"` //语言
|
||||
}
|
||||
|
||||
// CheckParams 校验邮箱参数
|
||||
|
||||
@ -3,10 +3,11 @@ package router
|
||||
import (
|
||||
"os"
|
||||
|
||||
common "go-admin/common/middleware"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk"
|
||||
common "go-admin/common/middleware"
|
||||
)
|
||||
|
||||
// InitRouter 路由初始化,不要怀疑,这里用到了
|
||||
|
||||
21
app/admin/router/invite_log.go
Normal file
21
app/admin/router/invite_log.go
Normal file
@ -0,0 +1,21 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/fronted"
|
||||
"go-admin/common/middleware"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
routerFrontedCheckRole = append(routerFrontedCheckRole, registerInviteLogFrontedRouter)
|
||||
}
|
||||
|
||||
// registerLineApiGroupRouter
|
||||
func registerInviteLogFrontedRouter(v1 *gin.RouterGroup) {
|
||||
api := fronted.InviteLog{}
|
||||
r := v1.Group("/invite-log")
|
||||
{
|
||||
r.GET("", middleware.FrontedAuth, api.GetPersonnalPage)
|
||||
}
|
||||
}
|
||||
@ -26,6 +26,7 @@ func registerLinePreOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM
|
||||
r.DELETE("", api.Delete)
|
||||
|
||||
r.POST("addOrder", actions.PermissionAction(), api.AddPreOrder) //添加订单
|
||||
// r.POST("position", actions.PermissionAction(), api.AddPosition) //手动加仓
|
||||
r.POST("batchAddOrder", actions.PermissionAction(), api.BatchAddOrder) //批量添加订单
|
||||
r.POST("quickAddPreOrder", actions.PermissionAction(), api.QuickAddPreOrder) //快捷下单
|
||||
r.POST("lever", actions.PermissionAction(), api.Lever) //设置杠杆
|
||||
|
||||
@ -5,8 +5,8 @@ import (
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/common/middleware"
|
||||
"go-admin/common/actions"
|
||||
"go-admin/common/middleware"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -23,5 +23,7 @@ func registerLineSymbolBlackRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJ
|
||||
r.POST("", api.Insert)
|
||||
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
||||
r.DELETE("", api.Delete)
|
||||
|
||||
r.GET("reload-symbol", api.RelodSymbol)
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/fronted"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
"go-admin/app/admin/fronted"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/common/actions"
|
||||
@ -25,6 +26,8 @@ func registerLineUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddl
|
||||
r.POST("", api.Insert)
|
||||
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
||||
r.DELETE("", api.Delete)
|
||||
|
||||
r.PUT("property", api.ReloadProperty) //更新资产
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,6 +48,12 @@ func frontedRegisterLinUserRouter(v1 *gin.RouterGroup) {
|
||||
r.POST("/addApiAuth", middleware.FrontedAuth, api.AddApiKey) //用户手动添加Apikey
|
||||
r.POST("/updateApiAuth", middleware.FrontedAuth, api.UpdateApiKey) //用户手动修改Apikey
|
||||
r.POST("/opStatus", middleware.FrontedAuth, api.OpenStatus) //开启或者关闭状态
|
||||
r.DELETE("/logout", middleware.FrontedAuth, api.Logout) //退出登录
|
||||
r.GET("user-info", middleware.FrontedAuth, api.GetUserInfo) //用户详情
|
||||
r.PUT("order-set", middleware.FrontedAuth, api.UserOrderSet) //用户下单设置
|
||||
r.PUT("reset-pwd", api.ResetPassword) //重置密码
|
||||
|
||||
r.GET("/exchange-balance", middleware.FrontedAuth, api.GetProperty) //合约用户交易所u资产
|
||||
|
||||
//充值
|
||||
r.POST("/notify", api.Notify) //uDun回调
|
||||
@ -56,6 +65,11 @@ func frontedRegisterLinUserRouter(v1 *gin.RouterGroup) {
|
||||
r.POST("/callback", api.CallBack) //coinGate 回调地址
|
||||
r.POST("/preorder", middleware.FrontedAuth, api.PreOrder) //coinGate 充值
|
||||
|
||||
commonApi := fronted.Common{}
|
||||
r2 := v1.Group("common")
|
||||
{
|
||||
r2.GET("default-set", commonApi.GetDefaultSet) //默认设置
|
||||
}
|
||||
}
|
||||
|
||||
func frontedUserCenterRouter(v1 *gin.RouterGroup) {
|
||||
|
||||
27
app/admin/router/line_user_setting.go
Normal file
27
app/admin/router/line_user_setting.go
Normal file
@ -0,0 +1,27 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/common/middleware"
|
||||
"go-admin/common/actions"
|
||||
)
|
||||
|
||||
func init() {
|
||||
routerCheckRole = append(routerCheckRole, registerLineUserSettingRouter)
|
||||
}
|
||||
|
||||
// registerLineUserSettingRouter
|
||||
func registerLineUserSettingRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||
api := apis.LineUserSetting{}
|
||||
r := v1.Group("/line-user-setting").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||
{
|
||||
r.GET("", actions.PermissionAction(), api.GetPage)
|
||||
r.GET("/:id", actions.PermissionAction(), api.Get)
|
||||
r.POST("", api.Insert)
|
||||
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
@ -5,12 +5,14 @@ import (
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/common/middleware"
|
||||
"go-admin/app/admin/fronted"
|
||||
"go-admin/common/actions"
|
||||
"go-admin/common/middleware"
|
||||
)
|
||||
|
||||
func init() {
|
||||
routerCheckRole = append(routerCheckRole, registerMemberBalanceLogRouter)
|
||||
routerFrontedCheckRole = append(routerFrontedCheckRole, registerMemberBalanceLogFrontedRouter)
|
||||
}
|
||||
|
||||
// registerMemberBalanceLogRouter
|
||||
@ -25,3 +27,12 @@ func registerMemberBalanceLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gin
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
func registerMemberBalanceLogFrontedRouter(v1 *gin.RouterGroup) {
|
||||
api := fronted.MemberBalanceLog{}
|
||||
|
||||
r := v1.Group("/member-balance-log", middleware.FrontedAuth)
|
||||
{
|
||||
r.GET("/personal", api.GetPage) //app 个人余额明细
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,12 +5,14 @@ import (
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/common/middleware"
|
||||
"go-admin/app/admin/fronted"
|
||||
"go-admin/common/actions"
|
||||
"go-admin/common/middleware"
|
||||
)
|
||||
|
||||
func init() {
|
||||
routerCheckRole = append(routerCheckRole, registerMemberRenwaLogRouter)
|
||||
routerFrontedCheckRole = append(routerFrontedCheckRole, registerMemberRenwaLogFrontedRouter)
|
||||
}
|
||||
|
||||
// registerMemberRenwaLogRouter
|
||||
@ -25,3 +27,13 @@ func registerMemberRenwaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJW
|
||||
r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
func registerMemberRenwaLogFrontedRouter(v1 *gin.RouterGroup) {
|
||||
api := fronted.MemberRenwalLog{}
|
||||
|
||||
f := v1.Group("/member-renwal", middleware.FrontedAuth)
|
||||
{
|
||||
f.GET("/list", api.GetPage)
|
||||
f.POST("/apply", api.Apply)
|
||||
}
|
||||
}
|
||||
|
||||
46
app/admin/router/member_withdrawal_log.go
Normal file
46
app/admin/router/member_withdrawal_log.go
Normal file
@ -0,0 +1,46 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
|
||||
"go-admin/app/admin/apis"
|
||||
"go-admin/app/admin/fronted"
|
||||
"go-admin/common/actions"
|
||||
"go-admin/common/middleware"
|
||||
)
|
||||
|
||||
func init() {
|
||||
routerCheckRole = append(routerCheckRole, registerMemberWithdrawalLogRouter)
|
||||
routerFrontedCheckRole = append(routerFrontedCheckRole, registerMemberWidthdrawalLogFrontedRouter)
|
||||
}
|
||||
|
||||
// registerMemberWithdrawalLogRouter
|
||||
func registerMemberWithdrawalLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||
api := apis.MemberWithdrawalLog{}
|
||||
r := v1.Group("/member-withdrawal-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||
{
|
||||
r.GET("", actions.PermissionAction(), api.GetPage)
|
||||
r.GET("/:id", actions.PermissionAction(), api.Get)
|
||||
r.POST("", api.Insert)
|
||||
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
||||
r.DELETE("", api.Delete)
|
||||
|
||||
r.PUT("/approve", actions.PermissionAction(), api.Process) //审核提现申请
|
||||
r.PUT("confirm", actions.PermissionAction(), api.Confirm) //确认提现申请
|
||||
}
|
||||
}
|
||||
|
||||
func registerMemberWidthdrawalLogFrontedRouter(v1 *gin.RouterGroup) {
|
||||
api := fronted.MemberWithdrawalLog{}
|
||||
|
||||
r := v1.Group("/member-withdrawal", middleware.FrontedAuth)
|
||||
{
|
||||
r.GET("", api.GetPage)
|
||||
// r.GET("/:id", api.Get)
|
||||
r.POST("", api.Apply)
|
||||
r.PUT("/cancel", api.Cancel)
|
||||
// r.PUT("/:id", api.Update)
|
||||
// r.DELETE("", api.Delete)
|
||||
}
|
||||
}
|
||||
47
app/admin/service/appservice/common.go
Normal file
47
app/admin/service/appservice/common.go
Normal file
@ -0,0 +1,47 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
adminservice "go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"go-admin/pkg/utility"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
)
|
||||
|
||||
type Common struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// 获取前端 默认设置
|
||||
func (e *Common) GetDefaultSet() (dto.FrontedDefaultSetResp, int) {
|
||||
result := dto.FrontedDefaultSetResp{}
|
||||
keys := []string{"control_telegram_link", "control_customer_service", "control_binance_referral", "member_min_order_amount"}
|
||||
configService := adminservice.SysConfig{Service: e.Service}
|
||||
configMaps := make(map[string]dto.GetSysConfigByKEYForServiceResp)
|
||||
configService.GetWithKeys(&keys, &configMaps)
|
||||
|
||||
if config, ok := configMaps["control_telegram_link"]; ok {
|
||||
result.TelegramLink = config.ConfigValue
|
||||
}
|
||||
|
||||
if config, ok := configMaps["control_customer_service"]; ok {
|
||||
result.CustomServiceLink = config.ConfigValue
|
||||
}
|
||||
|
||||
if config, ok := configMaps["control_binance_referral"]; ok {
|
||||
result.BinanceReferralLink = config.ConfigValue
|
||||
|
||||
params, _ := utility.ParseURLParams(result.BinanceReferralLink)
|
||||
|
||||
if code, ok := params["ref"]; ok {
|
||||
result.BinanceReferralCode = code
|
||||
}
|
||||
}
|
||||
|
||||
if config, ok := configMaps["member_min_order_amount"]; ok {
|
||||
result.MinOrderAmount = config.ConfigValue
|
||||
}
|
||||
|
||||
return result, statuscode.OK
|
||||
}
|
||||
55
app/admin/service/appservice/invite_log.go
Normal file
55
app/admin/service/appservice/invite_log.go
Normal file
@ -0,0 +1,55 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
cDto "go-admin/common/dto"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
)
|
||||
|
||||
type InviteLog struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
func (e *InviteLog) GetPage(req *dto.PersonnalInviteLogPageReq, list *[]dto.InviteLogResp, count *int64) error {
|
||||
var datas []models.LineUser
|
||||
var childs []models.LineUser
|
||||
pids := make([]int, 0)
|
||||
|
||||
if err := e.Orm.Model(&models.LineUser{}).Where("pid = ?", req.UserId).Scopes(cDto.Paginate(req.GetPageSize(), req.GetPageIndex())).Find(&datas).Count(count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range datas {
|
||||
pids = append(pids, v.Id)
|
||||
}
|
||||
if err := e.Orm.Model(&models.LineUser{}).Where("pid in (?)", pids).Find(&childs).Error; err != nil {
|
||||
logger.Error("查询子邀请失败", err)
|
||||
}
|
||||
|
||||
for _, v := range datas {
|
||||
item := dto.InviteLogResp{
|
||||
UserId: v.Id,
|
||||
NickName: v.Username,
|
||||
RegisterTime: v.CreatedAt.UnixNano() / int64(time.Millisecond),
|
||||
}
|
||||
|
||||
for _, v2 := range childs {
|
||||
if v2.Pid == v.Id {
|
||||
item.Childs = append(item.Childs, dto.InviteLogResp{
|
||||
UserId: v2.Id,
|
||||
NickName: v2.Nickname,
|
||||
RegisterTime: v2.CreatedAt.UnixNano() / int64(time.Millisecond),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*list = append(*list, item)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
258
app/admin/service/appservice/line_user.go
Normal file
258
app/admin/service/appservice/line_user.go
Normal file
@ -0,0 +1,258 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go-admin/app/admin/models"
|
||||
adminservice "go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
memberbalancechangesource "go-admin/common/const/dicts/member_balance_change_source"
|
||||
memberrenwalconfigstatus "go-admin/common/const/dicts/member_renwal_config_status"
|
||||
memberrenwallogstatus "go-admin/common/const/dicts/member_renwal_log_status"
|
||||
"go-admin/common/const/rediskey"
|
||||
"go-admin/common/helper"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"go-admin/pkg/utility"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type LineUser struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// 注册赠送默认套餐
|
||||
func (e *LineUser) SetDefaultRenwal(user *models.LineUser) error {
|
||||
var defaultRenwalConfig models.MemberRenwalConfig
|
||||
|
||||
if err := e.Orm.Model(&defaultRenwalConfig).Where("is_default =1 AND status =?", memberrenwalconfigstatus.ENABLE).First(&defaultRenwalConfig).Error; err != nil {
|
||||
|
||||
logger.Error("没有默认续费配置 err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
//续费时长
|
||||
if defaultRenwalConfig.DurationDay > 0 {
|
||||
renwalLog := models.MemberRenwaLog{
|
||||
RenwalId: defaultRenwalConfig.Id,
|
||||
RenwalName: defaultRenwalConfig.PackageName,
|
||||
UserId: user.Id,
|
||||
RenwalDuration: defaultRenwalConfig.DurationDay,
|
||||
Status: memberrenwallogstatus.PENDING,
|
||||
PayableAmount: defaultRenwalConfig.OriginalPrice,
|
||||
ActualPaymentAmount: decimal.Zero,
|
||||
PaymentTime: &now,
|
||||
}
|
||||
|
||||
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
expirationTime := time.Now().Add(time.Hour * 24 * time.Duration(defaultRenwalConfig.DurationDay))
|
||||
user.ExpirationTime = &expirationTime
|
||||
|
||||
if err := tx.Model(&user).Update("expiration_time", expirationTime).Error; err != nil {
|
||||
logger.Errorf("默认套餐修改过期时间失败 userid:%v err:%v", user.Id, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Create(&renwalLog).Error; err != nil {
|
||||
logger.Errorf("新增续费记录失败 userid:%v err:%v", user.Id, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Error("续费失败 err", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理过期账户
|
||||
func (e *LineUser) Expire() error {
|
||||
err := e.Orm.Model(&models.LineUser{}).Where("expiration_time <NOW() AND expiration_time IS NOT NULL ").Update("expiration_time", nil).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 会员开通支付回调
|
||||
func (e *LineUser) PayCallBack(datas []models.MemberRenwaLog) error {
|
||||
now := time.Now()
|
||||
// startTime := time.Now().Add(-4 * time.Hour)
|
||||
log := models.MemberRenwaLog{}
|
||||
configService := adminservice.SysConfig{Service: e.Service}
|
||||
keys := []string{"member_invitation_rate1", "member_invitation_rate2"}
|
||||
configs := make(map[string]dto.GetSysConfigByKEYForServiceResp)
|
||||
configService.GetWithKeys(&keys, &configs)
|
||||
renwalLogs := make([]models.MemberRenwaLog, 0)
|
||||
|
||||
if err := e.Orm.Model(&models.MemberRenwaLog{}).Where("expiration_time >NOW() and status =?", memberrenwallogstatus.PENDING).Find(&renwalLogs).Error; err != nil {
|
||||
logger.Error("查询未过期续费记录失败", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, data := range datas {
|
||||
err := e.doCallBack(data, log, renwalLogs, now, configs)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 回调逻辑
|
||||
func (e *LineUser) doCallBack(data models.MemberRenwaLog, log models.MemberRenwaLog, renwalLogs []models.MemberRenwaLog, now time.Time, configs map[string]dto.GetSysConfigByKEYForServiceResp) error {
|
||||
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.OrderCallBackLock, data.PayableAmount), 200, 5, 100*time.Millisecond)
|
||||
|
||||
if ok, err := lock.AcquireWait(context.Background()); err != nil {
|
||||
logger.Debug("获取锁失败", err)
|
||||
return err
|
||||
} else if ok {
|
||||
defer lock.Release()
|
||||
|
||||
// 检查是否已经处理过该订单
|
||||
hashKey := fmt.Sprintf(rediskey.MemberHash, data.Hash)
|
||||
val, _ := helper.DefaultRedis.GetString(hashKey)
|
||||
if val != "" {
|
||||
logger.Info("已处理过的hash:", data.Hash)
|
||||
return nil
|
||||
}
|
||||
|
||||
for index := range renwalLogs {
|
||||
if renwalLogs[index].PayableAmount.Cmp(data.PayableAmount) == 0 {
|
||||
// 查询续费记录
|
||||
if err := e.Orm.Model(&log).Where("payable_amount=? AND status =?", data.PayableAmount, memberrenwallogstatus.PENDING).First(&log).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
||||
// 如果记录未找到,跳过该项
|
||||
logger.Warnf("续费记录未找到 hash:%v amount:%v", data.Hash, data.PayableAmount)
|
||||
continue
|
||||
}
|
||||
logger.Errorf("续费记录查询失败 hash:%v amount:%v err:%v", data.Hash, data.PayableAmount, err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Status = memberrenwallogstatus.PAID
|
||||
log.PaymentTime = &now
|
||||
log.FromAddress = data.FromAddress
|
||||
log.ActualPaymentAmount = data.ActualPaymentAmount
|
||||
log.Hash = data.Hash
|
||||
|
||||
user := models.LineUser{}
|
||||
// 查询用户信息
|
||||
if err := e.Orm.Model(&user).Where("id =?", log.UserId).First(&user).Error; err != nil {
|
||||
logger.Errorf("用户查询失败 hash:%v amount:%v err:%v", data.Hash, data.PayableAmount, err)
|
||||
continue
|
||||
}
|
||||
// 更新 ExpirationTime
|
||||
if user.ExpirationTime != nil && user.ExpirationTime.After(now) {
|
||||
expirationTime := user.ExpirationTime.AddDate(0, 0, log.RenwalDuration)
|
||||
user.ExpirationTime = &expirationTime
|
||||
} else {
|
||||
expirationTime := now.AddDate(0, 0, log.RenwalDuration)
|
||||
user.ExpirationTime = &expirationTime
|
||||
}
|
||||
// 计算返现记录
|
||||
balanceLogs := make([]models.MemberBalanceLog, 0)
|
||||
if user.Pid > 0 {
|
||||
if set, ok := configs["member_invitation_rate1"]; ok {
|
||||
rate1 := utility.StrToDecimal(set.ConfigValue)
|
||||
if rate1.Cmp(decimal.Zero) > 0 {
|
||||
balanceLogs = append(balanceLogs, calculateBalance(user.Pid, data.PayableAmount, rate1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if user.TopReferrerId > 0 {
|
||||
if set, ok := configs["member_invitation_rate2"]; ok {
|
||||
rate1 := utility.StrToDecimal(set.ConfigValue)
|
||||
if rate1.Cmp(decimal.Zero) > 0 {
|
||||
balanceLogs = append(balanceLogs, calculateBalance(user.TopReferrerId, data.PayableAmount, rate1))
|
||||
}
|
||||
}
|
||||
}
|
||||
// 修改续期订单记录
|
||||
if err := e.Orm.Model(log).Save(&log).Error; err != nil {
|
||||
logger.Errorf("续费更新订单失败 userid:%v hash:%v amount:%v err:%v", user.Id, data.Hash, data.PayableAmount, err)
|
||||
continue
|
||||
}
|
||||
// 更新用户信息
|
||||
if err := e.Orm.Model(&user).Updates(user).Error; err != nil {
|
||||
logger.Errorf("续费更新失败 userid:%v hash:%v amount:%v err:%v", user.Id, data.Hash, data.PayableAmount, err)
|
||||
continue
|
||||
}
|
||||
// 事务操作,保存返现记录及更新余额
|
||||
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
// 保存返现记录
|
||||
if err := e.Orm.Model(&models.MemberBalanceLog{}).Create(&balanceLogs).Error; err != nil {
|
||||
logger.Errorf("续费保存返现记录失败 userid:%v hash:%v amount:%v err:%v", user.Id, data.Hash, data.PayableAmount, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新用户余额
|
||||
for _, item := range balanceLogs {
|
||||
if err := e.Orm.Exec("update member_balance set total_amount=total_amount+?,free_amount=free_amount +? where user_id=?", item.Amount, item.Amount, item.UserId).Error; err != nil {
|
||||
logger.Errorf("续费更新余额失败 userid:%v 返现userid:%v hash:%v amount:%v err:%v", user.Id, item.UserId, data.Hash, data.PayableAmount, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
// 事务失败处理
|
||||
if err != nil {
|
||||
logger.Errorf("续费成功,返现失败:续费userid:%v,hash:%s,err:%v", user.Id, data.Hash, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.SetStringExpire(hashKey, "1", time.Hour*1); err != nil {
|
||||
logger.Errorf("续费成功,写入hash缓存失败 :续费userid:%v,hash:%s,err:%v", user.Id, data.Hash, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 计算返现的函数
|
||||
func calculateBalance(userId int, amount decimal.Decimal, rate decimal.Decimal) models.MemberBalanceLog {
|
||||
return models.MemberBalanceLog{
|
||||
UserId: userId,
|
||||
ChangeSource: memberbalancechangesource.CASH_BACK,
|
||||
ChangeType: 1,
|
||||
Amount: amount.Mul(rate.Div(decimal.NewFromInt(100))).Truncate(2),
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户过期时间
|
||||
// return statuscode
|
||||
func (e *LineUser) GetUserInfo(userId int, data *dto.LineUserAppResp) int {
|
||||
user := models.LineUser{}
|
||||
userSetting := models.LineUserSetting{}
|
||||
|
||||
if err := e.Orm.Model(&user).Where("id = ?", userId).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.DataError
|
||||
}
|
||||
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
e.Orm.Model(&userSetting).Where("user_id = ?", userId).First(&userSetting)
|
||||
|
||||
if user.ExpirationTime != nil {
|
||||
data.ExpirationTimeUnix = user.ExpirationTime.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
data.MinOrderAmount = userSetting.MinOrderAmount
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
50
app/admin/service/appservice/member_balance_log.go
Normal file
50
app/admin/service/appservice/member_balance_log.go
Normal file
@ -0,0 +1,50 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/models"
|
||||
adminservice "go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
cDto "go-admin/common/dto"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
type MemberBalanceLog struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// 分页查询个人资金记录
|
||||
func (e *MemberBalanceLog) GetPage(req *dto.MemberBalanceLogPageAppReq, list *[]dto.MemberBalanceLogAppResp, count *int64) int {
|
||||
var data models.MemberBalanceLog
|
||||
datas := make([]models.MemberBalanceLog, 0)
|
||||
item := dto.MemberBalanceLogAppResp{}
|
||||
|
||||
err := e.Orm.Model(&data).
|
||||
Where("user_id =?", req.UserId).
|
||||
Scopes(
|
||||
cDto.MakeCondition(req.GetNeedSearch()),
|
||||
cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
|
||||
).
|
||||
Find(&datas).Limit(-1).Offset(-1).
|
||||
Count(count).Error
|
||||
|
||||
if err != nil {
|
||||
return statuscode.ServerError
|
||||
}
|
||||
dictService := adminservice.SysDictData{Service: e.Service}
|
||||
dicts, _ := dictService.GetByType("member_change_source")
|
||||
|
||||
for _, v := range datas {
|
||||
copier.Copy(&item, v)
|
||||
|
||||
item.CreateTimeUnix = v.CreatedAt.UnixNano() / int64(time.Millisecond)
|
||||
item.ChangeSourceName, _ = dictService.GetLanguageByDatas(&dicts, item.ChangeSource, req.Language)
|
||||
|
||||
*list = append(*list, item)
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
@ -2,6 +2,7 @@ package appservice
|
||||
|
||||
import (
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
memberrenwalconfigstatus "go-admin/common/const/dicts/member_renwal_config_status"
|
||||
memberrenwalisvisible "go-admin/common/const/dicts/member_renwal_isvisible"
|
||||
statuscode "go-admin/common/status_code"
|
||||
@ -13,10 +14,30 @@ type MemberRenwalConfigAppService struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
func (e *MemberRenwalConfigAppService) GetList() ([]models.MemberRenwalConfig, int) {
|
||||
result := make([]models.MemberRenwalConfig, 0)
|
||||
if err := e.Orm.Model(&models.MemberRenwalConfig{}).Where(" status =? AND is_visible =?", memberrenwalconfigstatus.ENABLE, memberrenwalisvisible.IsVisibleYes).Order("sort asc").Find(&result).Error; err != nil {
|
||||
func (e *MemberRenwalConfigAppService) GetList(language string) ([]dto.MemberRenwalConfigAppResp, int) {
|
||||
var datas []models.MemberRenwalConfig
|
||||
result := make([]dto.MemberRenwalConfigAppResp, 0)
|
||||
if err := e.Orm.Model(&models.MemberRenwalConfig{}).Where(" status =? AND is_visible =?",
|
||||
memberrenwalconfigstatus.ENABLE, memberrenwalisvisible.IsVisibleYes).
|
||||
Order("sort asc").Find(&datas).Error; err != nil {
|
||||
return result, statuscode.ServerError
|
||||
}
|
||||
|
||||
for _, v := range datas {
|
||||
item := dto.MemberRenwalConfigAppResp{
|
||||
Id: v.Id,
|
||||
PackageName: v.PackageName,
|
||||
OriginalPrice: v.OriginalPrice,
|
||||
DiscountPrice: v.DiscountPrice,
|
||||
DurationDay: v.DurationDay,
|
||||
Remark: v.Remark,
|
||||
}
|
||||
|
||||
if language != "zh_CN" {
|
||||
item.PackageName = v.PackageNameEn
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return result, statuscode.OK
|
||||
}
|
||||
|
||||
@ -1,13 +1,26 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go-admin/app/admin/models"
|
||||
adminservice "go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/dto"
|
||||
memberrenwalconfigstatus "go-admin/common/const/dicts/member_renwal_config_status"
|
||||
memberrenwallogstatus "go-admin/common/const/dicts/member_renwal_log_status"
|
||||
"go-admin/common/const/rediskey"
|
||||
cDto "go-admin/common/dto"
|
||||
"go-admin/common/helper"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"go-admin/pkg/utility"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type MemberRenwalLog struct {
|
||||
@ -15,28 +28,170 @@ type MemberRenwalLog struct {
|
||||
}
|
||||
|
||||
// 分页查询续期记录
|
||||
func (e *MemberRenwalLog) GetPage(userId int, req *dto.MemberRenwalLogPageAppReq, list *[]dto.MemberRenwalLogResp) int {
|
||||
var count int64
|
||||
func (e *MemberRenwalLog) GetPage(userId int, req *dto.MemberRenwalLogPageAppReq, list *[]dto.MemberRenwalLogResp, count *int64) int {
|
||||
var data models.MemberRenwaLog
|
||||
var datas []models.MemberRenwaLog
|
||||
resp := dto.MemberRenwalLogResp{}
|
||||
renwalIds := make([]int, 0)
|
||||
renwals := make([]models.MemberRenwalConfig, 0)
|
||||
|
||||
err := e.Orm.Model(&data).
|
||||
Where("user_id = ?", userId).
|
||||
Where("user_id = ? AND status !=?", userId, memberrenwallogstatus.EXPIRED).
|
||||
Scopes(
|
||||
cDto.MakeCondition(req.GetNeedSearch()),
|
||||
cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
|
||||
).
|
||||
Find(list).Limit(-1).Offset(-1).
|
||||
Count(&count).Error
|
||||
Find(&datas).Limit(-1).Offset(-1).
|
||||
Count(count).Error
|
||||
|
||||
if err != nil {
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
for _, item := range *list {
|
||||
for _, v := range datas {
|
||||
if utility.ContainsInt(renwalIds, v.RenwalId) {
|
||||
continue
|
||||
}
|
||||
renwalIds = append(renwalIds, v.RenwalId)
|
||||
}
|
||||
|
||||
e.Orm.Model(&models.MemberRenwalConfig{}).Where("id IN (?)", renwalIds).Find(&renwals)
|
||||
|
||||
for _, item := range datas {
|
||||
copier.Copy(&resp, item)
|
||||
|
||||
if item.PaymentTime != nil {
|
||||
resp.PaymentTimeUnix = item.PaymentTime.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
resp.ExpirationTimeUnix = item.ExpirationTime.UnixNano() / int64(time.Millisecond)
|
||||
|
||||
if req.Language != "zh_CN" {
|
||||
for _, v := range renwals {
|
||||
if v.Id == item.RenwalId {
|
||||
resp.RenwalName = v.PackageNameEn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*list = append(*list, resp)
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
// 续期订单
|
||||
func (e *MemberRenwalLog) Renwal(req *dto.MemberRenwalCreateAppReq, data *dto.MemberRenwalCreateAppResp) int {
|
||||
var renwalConfig models.MemberRenwalConfig
|
||||
renwalLog := models.MemberRenwaLog{}
|
||||
now := time.Now()
|
||||
configService := adminservice.SysConfig{Service: e.Service}
|
||||
configDict := map[string]dto.GetSysConfigByKEYForServiceResp{}
|
||||
expirationVal := 30
|
||||
var toAddress string
|
||||
|
||||
configService.GetWithKeys(&[]string{"member_renwal_expiration_val", "member_receive_address"}, &configDict)
|
||||
|
||||
if dict, ok := configDict["member_renwal_expiration_val"]; ok && dict.ConfigValue != "" {
|
||||
expirationVal = utility.ToInt(dict.ConfigValue)
|
||||
}
|
||||
|
||||
if dict, ok := configDict["member_receive_address"]; !ok || dict.ConfigValue == "" {
|
||||
logger.Errorf("钱包收款地址不存在")
|
||||
return statuscode.ServerError
|
||||
} else if dict.ConfigValue != "" {
|
||||
toAddress = dict.ConfigValue
|
||||
}
|
||||
|
||||
if err := e.Orm.Model(&renwalConfig).Where("id =?", req.ConfigId).First(&renwalConfig).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.DataError
|
||||
}
|
||||
|
||||
logger.Errorf("查询套餐详情失败,err:", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
if renwalConfig.Status != memberrenwalconfigstatus.ENABLE {
|
||||
return statuscode.RenwalConfigDisabled
|
||||
}
|
||||
|
||||
price := renwalConfig.OriginalPrice
|
||||
|
||||
if renwalConfig.DiscountPrice.Cmp(decimal.Zero) > 0 {
|
||||
price = renwalConfig.DiscountPrice
|
||||
}
|
||||
|
||||
amount, err := generateUniqueAmount(price, 3, 5, expirationVal)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("生成唯一金额失败,userId:%v err:%v", req.UserId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
renwalLog.RenwalId = req.ConfigId
|
||||
renwalLog.UserId = req.UserId
|
||||
renwalLog.RenwalName = renwalConfig.PackageName
|
||||
renwalLog.RenwalDuration = renwalConfig.DurationDay
|
||||
renwalLog.Status = memberrenwallogstatus.PENDING
|
||||
renwalLog.ExpirationTime = now.Add(time.Minute * time.Duration(expirationVal))
|
||||
renwalLog.Coin = "USDT"
|
||||
renwalLog.PayableAmount = amount
|
||||
renwalLog.NetworkName = "TRC20"
|
||||
renwalLog.ReceiveAddress = toAddress
|
||||
|
||||
if err := e.Orm.Model(&models.MemberRenwaLog{}).Create(&renwalLog).Error; err != nil {
|
||||
logger.Errorf("创建续费记录失败,userId:%v err:%v", req.UserId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
data.Amount = renwalLog.PayableAmount
|
||||
data.ExpirationTimeUnix = renwalLog.ExpirationTime.UnixNano() / int64(time.Millisecond)
|
||||
data.NetworkName = renwalLog.NetworkName
|
||||
data.ToAddress = renwalLog.ReceiveAddress
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
// 生成唯一的金额
|
||||
// base: 基础金额
|
||||
// decimalPlaces: 小数位数
|
||||
// maxRetries: 最大尝试次数
|
||||
// expirationVal: 过期时间(分钟)
|
||||
func generateUniqueAmount(base decimal.Decimal, decimalPlaces int, maxRetries int, expirationVal int) (decimal.Decimal, error) {
|
||||
// 尝试生成最大次数为 maxRetries
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
amount := GenerateRandomDecimal(base, decimalPlaces)
|
||||
|
||||
// 如果没有重复,返回生成的金额
|
||||
err := helper.DefaultRedis.SetAdd(fmt.Sprintf(rediskey.OrderAmount, amount), "1", time.Duration(expirationVal))
|
||||
if err == nil {
|
||||
// 插入成功,返回该金额
|
||||
return amount, nil
|
||||
}
|
||||
|
||||
// key 已存在,继续尝试
|
||||
if err.Error() == "key已存在" {
|
||||
fmt.Println("金额已存在,重试生成...")
|
||||
continue
|
||||
}
|
||||
// 成功,返回生成的金额
|
||||
return amount, nil
|
||||
}
|
||||
|
||||
// 超过最大重试次数,增加小数位数并递归
|
||||
return generateUniqueAmount(base, decimalPlaces+1, maxRetries, expirationVal)
|
||||
}
|
||||
|
||||
func GenerateRandomDecimal(base decimal.Decimal, decimalPlaces int) decimal.Decimal {
|
||||
// 生成一个随机的小数部分,最大为 1,但小数位数不超过指定的位数
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomFraction := rand.Float64()
|
||||
|
||||
// 将随机小数调整到指定的小数位数
|
||||
randomDecimal := decimal.NewFromFloat(randomFraction).Round(int32(decimalPlaces))
|
||||
|
||||
// 将原始的 decimal 加上随机小数部分
|
||||
result := base.Add(randomDecimal)
|
||||
|
||||
// 返回最终结果,确保精确到指定的小数位数
|
||||
return result.Round(int32(decimalPlaces))
|
||||
}
|
||||
|
||||
185
app/admin/service/appservice/member_withdrawal_log.go
Normal file
185
app/admin/service/appservice/member_withdrawal_log.go
Normal file
@ -0,0 +1,185 @@
|
||||
package appservice
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/pkg/utility"
|
||||
"time"
|
||||
|
||||
memberwithdrawallogstatus "go-admin/common/const/dicts/member_withdrawal_log_status"
|
||||
cDto "go-admin/common/dto"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLog struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
func (e *MemberWithdrawalLog) GetPage(req *dto.MemberWithdrawalLogGetPageAppReq, list *[]dto.MemberWithdrawalLogResp, count *int64) int {
|
||||
var err error
|
||||
var data models.MemberWithdrawalLog
|
||||
var datas []models.MemberWithdrawalLog
|
||||
userIds := make([]int, 0)
|
||||
|
||||
err = e.Orm.Model(&data).
|
||||
Scopes(
|
||||
cDto.MakeCondition(req.GetNeedSearch()),
|
||||
cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
|
||||
).
|
||||
Find(&datas).Limit(-1).Offset(-1).
|
||||
Count(count).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("MemberWithdrawalLogService GetPage error:%s \r\n", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
for _, user := range datas {
|
||||
if !utility.ContainsInt(userIds, user.UserId) {
|
||||
userIds = append(userIds, user.UserId)
|
||||
}
|
||||
}
|
||||
|
||||
userNames := make([]models.LineUser, 0)
|
||||
e.Orm.Model(&models.LineUser{}).Where("id in (?)", userIds).Select("id,nickname").Find(&userNames)
|
||||
|
||||
for _, v := range datas {
|
||||
item := dto.MemberWithdrawalLogResp{}
|
||||
copier.Copy(&item, &v)
|
||||
|
||||
for _, user := range userNames {
|
||||
if v.UserId == user.Id {
|
||||
item.NickName = user.Nickname
|
||||
}
|
||||
}
|
||||
|
||||
item.CreateTimeUnix = v.CreatedAt.UnixNano() / int64(time.Millisecond)
|
||||
|
||||
if v.ConfirmTime != nil {
|
||||
item.ConfirmTimeUnix = v.ConfirmTime.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
*list = append(*list, item)
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
// 用户提现申请
|
||||
// return statuscode
|
||||
func (e *MemberWithdrawalLog) Apply(req *dto.MemberWithdrawalLogApplyReq) int {
|
||||
// config:=adminservice.SysConfig{}
|
||||
var network models.LineCoinnetwork
|
||||
|
||||
if err := e.Orm.Model(&network).Where("id =?", req.NetworkId).First(&network).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.NetworkNotExist
|
||||
}
|
||||
|
||||
logger.Errorf("查询网络失败 网络id:%v err:%v", req.NetworkId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
if network.Status != 1 {
|
||||
return statuscode.NetworkUnAvailable
|
||||
}
|
||||
|
||||
//小于最小提现金额
|
||||
if req.Amount.Cmp(network.MinWithdrawal) < 0 {
|
||||
return statuscode.BelowMinimum
|
||||
}
|
||||
|
||||
fee := req.Amount.Mul(network.Fee.Div(decimal.NewFromInt(100))).Truncate(2)
|
||||
code := statuscode.OK
|
||||
log := models.MemberWithdrawalLog{
|
||||
UserId: req.UserId,
|
||||
NetworkId: req.NetworkId,
|
||||
NetworkName: network.NetworkName,
|
||||
Amount: req.Amount,
|
||||
ToAddress: req.ToAddress,
|
||||
Status: memberwithdrawallogstatus.PENDING,
|
||||
Fee: fee,
|
||||
}
|
||||
|
||||
//事务
|
||||
e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
balance := models.MemberBalance{}
|
||||
|
||||
if err := tx.Model(&balance).Where("user_id = ?", req.UserId).First(&balance).Error; err != nil {
|
||||
code = statuscode.InsufficientFunds
|
||||
return err
|
||||
}
|
||||
|
||||
frozenAmount := fee.Add(req.Amount)
|
||||
if frozenAmount.Cmp(balance.FreeAmount) > 0 {
|
||||
code = statuscode.InsufficientFunds
|
||||
return errors.New("余额不足")
|
||||
}
|
||||
|
||||
balance.FreeAmount = balance.FreeAmount.Sub(frozenAmount)
|
||||
balance.FrozenAmount = balance.FrozenAmount.Add(frozenAmount)
|
||||
|
||||
if err := tx.Create(&log).Error; err != nil {
|
||||
code = statuscode.ServerError
|
||||
logger.Errorf("创建提现记录失败 userid:%d, err:%v", req.UserId, err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&balance).Updates(map[string]interface{}{
|
||||
"free_amount": balance.FreeAmount,
|
||||
"frozen_amount": balance.FrozenAmount,
|
||||
}).Error; err != nil {
|
||||
code = statuscode.ServerError
|
||||
logger.Errorf("更新余额失败 userid:%v err:%v", req.UserId, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
// 取消提现
|
||||
func (e *MemberWithdrawalLog) Canceled(req *dto.MemberWithdrawalLogCancelReq, userId int) int {
|
||||
code := statuscode.OK
|
||||
|
||||
e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
var log models.MemberWithdrawalLog
|
||||
if err := tx.Model(&log).Where("id = ? AND user_id =?", req.Id, userId).First(&log).Error; err != nil {
|
||||
code = statuscode.DataError
|
||||
return err
|
||||
}
|
||||
|
||||
if log.Status != memberwithdrawallogstatus.PENDING {
|
||||
code = statuscode.CanNotCancel
|
||||
return errors.New("提现记录状态错误")
|
||||
}
|
||||
|
||||
log.Status = memberwithdrawallogstatus.CANCELED
|
||||
totalAmount := log.Amount.Add(log.Fee)
|
||||
|
||||
if err := tx.Exec("UPDATE member_balance SET free_amount=free_amount+?,frozen_amount=frozen_amount-? WHERE user_id =?", totalAmount, totalAmount, log.UserId).Error; err != nil {
|
||||
code = statuscode.ServerError
|
||||
logger.Errorf("更新余额失败 提现订单:id userid:%v err:%v", req.Id, userId, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&log).Update("status", log.Status).Error; err != nil {
|
||||
code = statuscode.ServerError
|
||||
logger.Errorf("更新提现订单状态失败 提现订单:id userid:%v err:%v", req.Id, userId, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return code
|
||||
}
|
||||
@ -44,15 +44,15 @@ func GetDeviceID(ctx *gin.Context) string {
|
||||
return device
|
||||
}
|
||||
|
||||
// 获取 language,默认语言:zh-CN
|
||||
// 获取 language,默认语言:zh_CN
|
||||
// 英语 en
|
||||
// 日本语 jp
|
||||
// 韩语 kr
|
||||
// 马来西亚语 my
|
||||
// 泰国语 th
|
||||
// 越南语 vn
|
||||
// 简体中文 zh-CN
|
||||
// 繁体中文 zh-HK
|
||||
// 简体中文 zh_CN
|
||||
// 繁体中文 zh_HK
|
||||
func GetLanguage(ctx *gin.Context) string {
|
||||
lang := ""
|
||||
|
||||
@ -62,7 +62,7 @@ func GetLanguage(ctx *gin.Context) string {
|
||||
val, exits := ctx.Get("language")
|
||||
|
||||
if !exits {
|
||||
lang = "zh-CN"
|
||||
lang = "zh_CN"
|
||||
} else {
|
||||
lang = val.(string)
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ type LineCoinnetworkInsertReq struct {
|
||||
UnlockTime int64 `json:"unlockTime" comment:"提现确认平均时间,单位分钟"`
|
||||
Fee decimal.Decimal `json:"fee" comment:"网络手续费百分比"`
|
||||
MinWithdrawal decimal.Decimal `json:"minWithdrawal" comment:"最小提现金额"`
|
||||
Status int `json:"status" comment:"状态"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
@ -62,6 +63,7 @@ func (s *LineCoinnetworkInsertReq) Generate(model *models.LineCoinnetwork) {
|
||||
model.UnlockTime = s.UnlockTime
|
||||
model.Fee = s.Fee
|
||||
model.MinWithdrawal = s.MinWithdrawal
|
||||
model.Status = s.Status
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
}
|
||||
|
||||
@ -78,6 +80,7 @@ type LineCoinnetworkUpdateReq struct {
|
||||
UnlockTime int64 `json:"unlockTime" comment:"提现确认平均时间,单位分钟"`
|
||||
Fee decimal.Decimal `json:"fee" comment:"网络手续费百分比"`
|
||||
MinWithdrawal decimal.Decimal `json:"minWithdrawal" comment:"最小提现金额"`
|
||||
Status int `json:"status" comment:"状态"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
@ -92,6 +95,7 @@ func (s *LineCoinnetworkUpdateReq) Generate(model *models.LineCoinnetwork) {
|
||||
model.UnlockTime = s.UnlockTime
|
||||
model.Fee = s.Fee
|
||||
model.MinWithdrawal = s.MinWithdrawal
|
||||
model.Status = s.Status
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package dto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
@ -191,7 +192,9 @@ type LineAddPreOrderReq struct {
|
||||
PricePattern string `json:"price_pattern"` //价格模式
|
||||
Price string `json:"price" vd:"$>0"` //下单价百分比
|
||||
Profit string `json:"profit" vd:"$>0"` //止盈价
|
||||
// StopPrice string `json:"stop_price"` //止损价
|
||||
ProfitNumRatio decimal.Decimal `json:"profit_num_ratio"` //止盈数量百分比
|
||||
ProfitTpTpPriceRatio decimal.Decimal `json:"profit_tp_tp_price_ratio"` //止盈后止盈价百分比
|
||||
ProfitTpSlPriceRatio decimal.Decimal `json:"profit_tp_sl_price_ratio"` //止盈后止损价百分比
|
||||
PriceType string `json:"price_type"` //价格类型
|
||||
SaveTemplate string `json:"save_template"` //是否保存模板
|
||||
TemplateName string `json:"template_name"` //模板名字
|
||||
@ -208,6 +211,63 @@ type LineAddPreOrderReq struct {
|
||||
Ext []LineAddPreOrderExtReq `json:"ext" ` //拓展字段
|
||||
}
|
||||
|
||||
type LinePreOrderAddPositionReq struct {
|
||||
ExchangeType string `json:"exchangeType" vd:"len($)>0"` //交易所类型
|
||||
OrderType int `json:"orderType"` //订单类型
|
||||
Symbol string `json:"symbol"` //交易对
|
||||
ApiUserId int `json:"apiId" ` //下单用户
|
||||
Site string `json:"site" ` //购买方向
|
||||
BuyPrice decimal.Decimal `json:"buyPrice" vd:"$>0"` //购买金额 U
|
||||
PricePattern string `json:"pricePattern"` //价格模式
|
||||
Price decimal.Decimal `json:"price" vd:"$>0"` //下单价百分比
|
||||
Profit decimal.Decimal `json:"profit" vd:"$>0"` //止盈价
|
||||
// StopPrice string `json:"stop_price"` //止损价
|
||||
AddPositionOrderType string `json:"addPositionOrderType" comment:"加仓订单类型 LIMIT-限价 MARKET-市价"`
|
||||
PriceType string `json:"priceType"` //价格类型
|
||||
ReTakeProfitRatio decimal.Decimal `json:"reTakeProfitRatio" comment:"亏损回本止盈百分比"`
|
||||
ReducePriceRatio decimal.Decimal `json:"reducePriceRatio" comment:"减仓价格百分比" `
|
||||
ReduceNumRatio decimal.Decimal `json:"reduceNumRatio" comment:"减仓数量百分比" `
|
||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduceTakeProfitRatio" comment:"减仓后止盈百分比" `
|
||||
ReduceStopLossRatio decimal.Decimal `json:"reduceStopLossRatio" comment:"减仓后止损百分比"`
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (req *LinePreOrderAddPositionReq) Valid() error {
|
||||
if req.ExchangeType == "" {
|
||||
return errors.New("交易所类型不能为空")
|
||||
}
|
||||
|
||||
if req.OrderType <= 0 || req.OrderType > 2 {
|
||||
return errors.New("订单类型错误")
|
||||
}
|
||||
|
||||
if req.Symbol == "" {
|
||||
return errors.New("交易对不能为空")
|
||||
}
|
||||
|
||||
if req.AddPositionOrderType == "" {
|
||||
return errors.New("加仓订单类型不能为空")
|
||||
}
|
||||
|
||||
if req.PriceType == "" {
|
||||
return errors.New("价格类型不能为空")
|
||||
}
|
||||
|
||||
if req.ReducePriceRatio.IsZero() {
|
||||
return errors.New("主单减仓价格百分比不能为空")
|
||||
}
|
||||
|
||||
if req.ReduceNumRatio.IsZero() {
|
||||
return errors.New("主单减仓数量百分比不能为空")
|
||||
}
|
||||
|
||||
if req.ReduceTakeProfitRatio.IsZero() {
|
||||
return errors.New("减仓后止盈百分比不能为空")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (req LineAddPreOrderReq) Valid() error {
|
||||
if req.ReducePriceRatio.IsZero() {
|
||||
return errors.New("主单减仓价格百分比不能为空")
|
||||
@ -217,25 +277,43 @@ func (req LineAddPreOrderReq) Valid() error {
|
||||
return errors.New("主单减仓数量百分比不能为空")
|
||||
}
|
||||
|
||||
if req.ReducePriceRatio.IsZero() || req.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) >= 0 {
|
||||
return errors.New("主单减仓价格百分比错误")
|
||||
}
|
||||
|
||||
for _, v := range req.Ext {
|
||||
name := "加仓"
|
||||
|
||||
if v.AddType < 1 || v.AddType > 2 {
|
||||
return errors.New("加、减仓单类型错误")
|
||||
}
|
||||
|
||||
if v.AddType == 2 {
|
||||
name = "减仓"
|
||||
}
|
||||
|
||||
if v.AddPositionVal.IsZero() {
|
||||
return errors.New("加仓单数量不能为空")
|
||||
return fmt.Errorf("%s单数量不能为空", name)
|
||||
}
|
||||
if v.AddPositionPriceRatio.IsZero() {
|
||||
return errors.New("加仓单下跌价格不能为空")
|
||||
if v.PriceRatio.Cmp(decimal.Zero) <= 0 || v.PriceRatio.Cmp(decimal.NewFromInt(100)) >= 0 {
|
||||
return fmt.Errorf("%s单下跌价格不能为空", name)
|
||||
}
|
||||
|
||||
if v.ReduceNumRatio.IsZero() || v.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓数量不正确")
|
||||
if v.TakeProfitRatio.IsZero() || v.TakeProfitRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("止盈价格不正确")
|
||||
}
|
||||
|
||||
if v.ReducePriceRatio.IsZero() || v.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓下跌价格不正确")
|
||||
if v.AddType == 1 && v.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) < 0 &&
|
||||
v.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 &&
|
||||
(v.TpTpPriceRatio.IsZero() || v.TpTpPriceRatio.Cmp(decimal.NewFromInt(100)) > 0) {
|
||||
return errors.New("止盈后止盈价格不正确")
|
||||
}
|
||||
|
||||
if v.ReduceTakeProfitRatio.IsZero() || v.ReduceTakeProfitRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓后止盈价格不正确")
|
||||
}
|
||||
// if v.AddType == 1 && v.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) < 0 &&
|
||||
// v.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 &&
|
||||
// (v.TpSlPriceRatio.Cmp(decimal.Zero) <= 0 || v.TpSlPriceRatio.Cmp(decimal.NewFromInt(100)) > 0) {
|
||||
// return errors.New("止盈后止损价格不正确")
|
||||
// }
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -285,6 +363,9 @@ type LineBatchAddPreOrderReq struct {
|
||||
BuyPrice string `json:"buy_price"` //购买金额 U
|
||||
PricePattern string `json:"price_pattern"` //价格模式
|
||||
Price string `json:"price"` //下单价百分比
|
||||
ProfitNumRatio decimal.Decimal `json:"profit_num_ratio"` //止盈数量百分比
|
||||
ProfitTpTpPriceRatio decimal.Decimal `json:"profit_tp_tp_price_ratio"` //止盈后止盈价百分比
|
||||
ProfitTpSlPriceRatio decimal.Decimal `json:"profit_tp_sl_price_ratio"` //止盈后止损价百分比
|
||||
Profit string `json:"profit"` //止盈价
|
||||
StopPrice string `json:"stop_price"` //止损价
|
||||
PriceType string `json:"price_type"` //价格类型
|
||||
@ -335,24 +416,36 @@ func (req LineBatchAddPreOrderReq) CheckParams() error {
|
||||
}
|
||||
|
||||
for _, v := range req.Ext {
|
||||
name := "加仓"
|
||||
|
||||
if v.AddType < 1 || v.AddType > 2 {
|
||||
return errors.New("加、减仓单类型错误")
|
||||
}
|
||||
|
||||
if v.AddType == 2 {
|
||||
name = "减仓"
|
||||
}
|
||||
|
||||
if v.AddPositionVal.IsZero() {
|
||||
return errors.New("加仓单数量不能为空")
|
||||
return fmt.Errorf("%s单数量不能为空", name)
|
||||
}
|
||||
if v.AddPositionPriceRatio.IsZero() {
|
||||
return errors.New("加仓单下跌价格不能为空")
|
||||
if v.PriceRatio.Cmp(decimal.Zero) <= 0 || v.PriceRatio.Cmp(decimal.NewFromInt(100)) >= 0 {
|
||||
return fmt.Errorf("%s单下跌价格不能为空", name)
|
||||
}
|
||||
|
||||
if v.ReduceNumRatio.IsZero() || v.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓数量不正确")
|
||||
if v.TakeProfitRatio.IsZero() || v.TakeProfitRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("止盈价格不正确")
|
||||
}
|
||||
|
||||
if v.ReducePriceRatio.IsZero() || v.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓下跌价格不正确")
|
||||
if v.AddType == 1 && v.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) < 0 &&
|
||||
v.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 &&
|
||||
(v.TpTpPriceRatio.IsZero() || v.TpTpPriceRatio.Cmp(decimal.NewFromInt(100)) > 0) {
|
||||
return errors.New("止盈后止盈价格不正确")
|
||||
}
|
||||
|
||||
if v.ReduceTakeProfitRatio.IsZero() || v.ReduceTakeProfitRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
return errors.New("减仓后止盈价格不正确")
|
||||
}
|
||||
// if v.TpSlPriceRatio.Cmp(decimal.Zero) <= 0 || v.TpSlPriceRatio.Cmp(decimal.NewFromInt(100)) > 0 {
|
||||
// return errors.New("止盈后止损价格不正确")
|
||||
// }
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -491,6 +584,7 @@ type ClosePosition struct {
|
||||
Rate string `json:"rate"` //限价平仓百分比
|
||||
CloseType int `json:"close_type"` //现货平仓=1 合约平仓=2
|
||||
ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type
|
||||
Side string `json:"side"` //SELL=卖出(空) BUY=买入(多)
|
||||
}
|
||||
|
||||
func (m *ClosePosition) CheckParams() error {
|
||||
@ -522,12 +616,12 @@ type CalculateBreakEevenRatioReq struct {
|
||||
Symbol string `form:"symbol"` //交易对
|
||||
ExchangeType string `form:"exchangeType"` //交易所类型 字典exchange_type
|
||||
SymbolType int `form:"symbolType"`
|
||||
AddType int `form:"addType" comment:"类型 1-加仓 2-减仓"`
|
||||
BuyPrice decimal.Decimal `form:"buyPrice"` //主单购买总金额
|
||||
LossBeginPercent decimal.Decimal `form:"lossBeginPercent"` //亏损开始百分比
|
||||
LossEndPercent decimal.Decimal `form:"lossEndPercent"` //亏损截至百分比
|
||||
AddPositionType int `form:"addPositionType"` //加仓类型 1-百分比 2-实际金额
|
||||
AddPositionVal decimal.Decimal `form:"addPositionVal"` //加仓金额
|
||||
ReducePercent decimal.Decimal `form:"reducePercent"` //减仓百分比
|
||||
AddPositionType int `form:"addPositionType"` //加仓/减仓 类型 1-百分比 2-实际金额
|
||||
AddPositionVal decimal.Decimal `form:"addPositionVal"` //加仓/减仓 金额
|
||||
RemainingQuantity decimal.Decimal `form:"remainingQuantity"` //剩余数量
|
||||
TotalLossAmountU decimal.Decimal `form:"totalLossAmountU"` //累计亏损金额
|
||||
}
|
||||
|
||||
@ -37,29 +37,30 @@ func (m *LinePreOrderExtGetPageReq) GetNeedSearch() interface{} {
|
||||
}
|
||||
|
||||
type LineAddPreOrderExtReq struct {
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" comment:"止盈百分比" `
|
||||
ReTakeProfitRatio decimal.Decimal `json:"reTakeProfitRatio" comment:"亏损回本止盈百分比"`
|
||||
ReducePriceRatio decimal.Decimal `json:"reducePriceRatio" comment:"减仓价格百分比" `
|
||||
ReduceNumRatio decimal.Decimal `json:"reduceNumRatio" comment:"减仓数量百分比" `
|
||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduceTakeProfitRatio" comment:"减仓后止盈百分比" `
|
||||
ReduceStopLossRatio decimal.Decimal `json:"reduceStopLossRatio" comment:"减仓后止损百分比"`
|
||||
ReduceReTakeProfitRatio decimal.Decimal `json:"reduceReTakeProfitRatio" comment:"减仓后回本止盈百分比"`
|
||||
AddPositionPriceRatio decimal.Decimal `json:"addPositionPriceRatio" comment:"加仓价格百分比" `
|
||||
AddPositionOrderType string `json:"addPositionOrderType" comment:"加仓订单类型 LIMIT-限价 MARKET-市价"`
|
||||
AddType int `json:"addType" comment:"类型 1-加仓 2-减仓"`
|
||||
OrderType string `json:"orderType" comment:"订单类型 LIMIT-限价 MARKET-市价"`
|
||||
PriceRatio decimal.Decimal `json:"priceRatio" comment:"价格百分比"`
|
||||
AddPositionType int `json:"addPositionType" comment:"加仓类型 1-百分比 2-实际金额"`
|
||||
AddPositionVal decimal.Decimal `json:"addPositionVal" comment:"加仓值"`
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" comment:"止盈百分比"`
|
||||
StopLossRatio decimal.Decimal `json:"stopLossRatio" comment:"止损百分比"`
|
||||
TakeProfitNumRatio decimal.Decimal `json:"takeProfitNumRatio" comment:"止盈数量百分比"`
|
||||
TpTpPriceRatio decimal.Decimal `json:"tpTpPriceRatio" comment:"止盈后止盈价格百分比"`
|
||||
TpSlPriceRatio decimal.Decimal `json:"tpSlPriceRatio" comment:"止盈后止损价格百分比"`
|
||||
ReTakeProfitRatio decimal.Decimal `json:"reTakeProfitRatio" comment:"亏损回本止盈百分比"`
|
||||
}
|
||||
|
||||
type LinePreOrderExtInsertReq struct {
|
||||
Id int `json:"-" comment:"主键id"` // 主键id
|
||||
MainOrderId int `json:"mainOrderId" comment:"主单id"`
|
||||
OrderId int `json:"orderId" comment:"订单id"`
|
||||
AddType int `json:"addType" comment:"类型 1-加仓 2-减仓"`
|
||||
OrderType string `json:"orderType" comment:"类型 LIMIT-限价 MARKET-市价"`
|
||||
PriceRatio decimal.Decimal `json:"priceRatio" comment:"价格百分比"`
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" comment:"止盈百分比"`
|
||||
ReducePriceRatio decimal.Decimal `json:"reducePriceRatio" comment:"减仓价格百分比"`
|
||||
ReduceNumRatio decimal.Decimal `json:"reduceNumRatio" comment:"减仓数量百分比"`
|
||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduceTakeProfitRatio" comment:"减仓后止盈百分比"`
|
||||
ReduceStopLossRatio decimal.Decimal `json:"reduceStopLossRatio" comment:"减仓后止损百分比"`
|
||||
AddPositionPriceRatio decimal.Decimal `json:"addPositionPriceRatio" comment:"加仓价格百分比"`
|
||||
TakeProfitNumRatio decimal.Decimal `json:"takeProfitNumRatio" comment:"止盈数量百分比"`
|
||||
TpTpPriceRatio decimal.Decimal `json:"tpTpPriceRatio" comment:"止盈后止盈价格百分比"`
|
||||
TpSlPriceRatio decimal.Decimal `json:"tpSlPriceRatio" comment:"止盈后止损价格百分比"`
|
||||
AddPositionType int `json:"addPositionType" comment:"加仓类型 1-百分比 2-实际金额"`
|
||||
AddPositionVal decimal.Decimal `json:"addPositionVal" comment:"加仓值"`
|
||||
common.ControlBy
|
||||
@ -72,11 +73,11 @@ func (s *LinePreOrderExtInsertReq) Generate(model *models.LinePreOrderExt) {
|
||||
model.MainOrderId = s.MainOrderId
|
||||
model.OrderId = s.OrderId
|
||||
model.TakeProfitRatio = s.TakeProfitRatio
|
||||
model.ReducePriceRatio = s.ReducePriceRatio
|
||||
model.ReduceNumRatio = s.ReduceNumRatio
|
||||
model.ReduceTakeProfitRatio = s.ReduceTakeProfitRatio
|
||||
model.ReduceStopLossRatio = s.ReduceStopLossRatio
|
||||
model.AddPositionPriceRatio = s.AddPositionPriceRatio
|
||||
model.AddType = s.AddType
|
||||
model.OrderType = s.OrderType
|
||||
model.PriceRatio = s.PriceRatio
|
||||
model.TpSlPriceRatio = s.TpSlPriceRatio
|
||||
model.TpSlPriceRatio = s.TpSlPriceRatio
|
||||
model.AddPositionType = s.AddPositionType
|
||||
model.AddPositionVal = s.AddPositionVal
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
@ -90,12 +91,13 @@ type LinePreOrderExtUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键id"` // 主键id
|
||||
MainOrderId int `json:"mainOrderId" comment:"主单id"`
|
||||
OrderId int `json:"orderId" comment:"订单id"`
|
||||
AddType int `json:"addType" comment:"类型 1-加仓 2-减仓"`
|
||||
OrderType string `json:"orderType" comment:"类型 LIMIT-限价 MARKET-市价"`
|
||||
PriceRatio decimal.Decimal `json:"priceRatio" comment:"价格百分比"`
|
||||
TakeProfitRatio decimal.Decimal `json:"takeProfitRatio" comment:"止盈百分比"`
|
||||
ReducePriceRatio decimal.Decimal `json:"reducePriceRatio" comment:"减仓价格百分比"`
|
||||
ReduceNumRatio decimal.Decimal `json:"reduceNumRatio" comment:"减仓数量百分比"`
|
||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduceTakeProfitRatio" comment:"减仓后止盈百分比"`
|
||||
ReduceStopLossRatio decimal.Decimal `json:"reduceStopLossRatio" comment:"减仓后止损百分比"`
|
||||
AddPositionPriceRatio decimal.Decimal `json:"addPositionPriceRatio" comment:"加仓价格百分比"`
|
||||
TakeProfitNumRatio decimal.Decimal `json:"takeProfitNumRatio" comment:"止盈数量百分比"`
|
||||
TpTpPriceRatio decimal.Decimal `json:"tpTpPriceRatio" comment:"止盈后止盈价格百分比"`
|
||||
TpSlPriceRatio decimal.Decimal `json:"tpSlPriceRatio" comment:"止盈后止损价格百分比"`
|
||||
AddPositionType int `json:"addPositionType" comment:"加仓类型 1-百分比 2-实际金额"`
|
||||
AddPositionVal decimal.Decimal `json:"addPositionVal" comment:"加仓值"`
|
||||
common.ControlBy
|
||||
@ -108,11 +110,11 @@ func (s *LinePreOrderExtUpdateReq) Generate(model *models.LinePreOrderExt) {
|
||||
model.MainOrderId = s.MainOrderId
|
||||
model.OrderId = s.OrderId
|
||||
model.TakeProfitRatio = s.TakeProfitRatio
|
||||
model.ReducePriceRatio = s.ReducePriceRatio
|
||||
model.ReduceNumRatio = s.ReduceNumRatio
|
||||
model.ReduceTakeProfitRatio = s.ReduceTakeProfitRatio
|
||||
model.ReduceStopLossRatio = s.ReduceStopLossRatio
|
||||
model.AddPositionPriceRatio = s.AddPositionPriceRatio
|
||||
model.AddType = s.AddType
|
||||
model.OrderType = s.OrderType
|
||||
model.PriceRatio = s.PriceRatio
|
||||
model.TpSlPriceRatio = s.TpSlPriceRatio
|
||||
model.TpSlPriceRatio = s.TpSlPriceRatio
|
||||
model.AddPositionType = s.AddPositionType
|
||||
model.AddPositionVal = s.AddPositionVal
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"github.com/shopspring/decimal"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"go-admin/pkg/emailhelper"
|
||||
"go-admin/pkg/utility"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
@ -210,11 +211,13 @@ type FrontedUserVerifyEmailReq struct {
|
||||
|
||||
type FrontedSendVerifyEmailReq struct {
|
||||
Email string `json:"email"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
type FrontedSendVerifySmsReq struct {
|
||||
PhoneAreaCode string `json:"phone_area_code"` // 区域电话代码
|
||||
Phone string `json:"phone"` // 手机号码
|
||||
Type int `json:"type" comment:"类型 0-注册 1-忘记密码"`
|
||||
}
|
||||
|
||||
func (receiver *FrontedSendVerifyEmailReq) CheckParams() int {
|
||||
@ -330,3 +333,80 @@ type VtsRechargePreOrderResp struct {
|
||||
PriceAmount string `json:"priceAmount"`
|
||||
PriceCurrency string `json:"priceCurrency"`
|
||||
}
|
||||
|
||||
type PersonnalInviteLogPageReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
UserId int `json:"userId" form:"userId"`
|
||||
}
|
||||
|
||||
type InviteLogResp struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
RegisterTime int64 `json:"registerTime"`
|
||||
NickName string `json:"nickName"`
|
||||
Childs []InviteLogResp `json:"childs"`
|
||||
}
|
||||
|
||||
type LineUserPropertyResp struct {
|
||||
SpotTotalAmount decimal.Decimal `json:"spotTotalAmount"` //现货U总资产
|
||||
SpotFreeAmount decimal.Decimal `json:"spotFreeAmount"` //现货U可用余额
|
||||
FuturesTotalAmount decimal.Decimal `json:"futuresTotalAmount"` //合约U总资产
|
||||
FuturesFreeAmount decimal.Decimal `json:"futuresFreeAmount"` //合约U可用余额
|
||||
}
|
||||
|
||||
type LineUserAppResp struct {
|
||||
ExpirationTimeUnix int64 `json:"expirationTimeUnix"`
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount"`
|
||||
}
|
||||
|
||||
type LineUserOrderSetReq struct {
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount"`
|
||||
}
|
||||
|
||||
type LineUserResetPwdReq struct {
|
||||
Pwd string `json:"pwd"`
|
||||
CheckPwd string `json:"check_pwd" comment:"确认密码"`
|
||||
PhoneAreaCode string `json:"phone_area_code" comment:"区号"`
|
||||
Code string `json:"code"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Type int `json:"type" comment:"类型 1-手机验证码 2-邮箱验证码"`
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
func (e *LineUserResetPwdReq) Valid() int {
|
||||
if e.Pwd == "" {
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
|
||||
if e.Code == "" {
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
|
||||
if e.CheckPwd != e.Pwd {
|
||||
return statuscode.UserResetPasswordInconsistency
|
||||
}
|
||||
|
||||
switch e.Type {
|
||||
case 1:
|
||||
if e.Phone == "" {
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
|
||||
if e.PhoneAreaCode == "" {
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
case 2:
|
||||
if e.Email == "" {
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
default:
|
||||
return statuscode.ParameterInvalid
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
type LineUserReloadPropertyReq struct {
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
|
||||
99
app/admin/service/dto/line_user_setting.go
Normal file
99
app/admin/service/dto/line_user_setting.go
Normal file
@ -0,0 +1,99 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type LineUserSettingGetPageReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
LineUserSettingOrder
|
||||
}
|
||||
|
||||
type LineUserSettingOrder struct {
|
||||
Id string `form:"idOrder" search:"type:order;column:id;table:line_user_setting"`
|
||||
MinOrderAmount string `form:"minOrderAmountOrder" search:"type:order;column:min_order_amount;table:line_user_setting"`
|
||||
SpotUsdtFreeAmount string `form:"spotUsdtFreeAmountOrder" search:"type:order;column:spot_usdt_free_amount;table:line_user_setting"`
|
||||
FutureUsdtTotalAmount string `form:"futureUsdtTotalAmountOrder" search:"type:order;column:future_usdt_total_amount;table:line_user_setting"`
|
||||
AssetUpdateTime string `form:"assetUpdateTimeOrder" search:"type:order;column:asset_update_time;table:line_user_setting"`
|
||||
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_user_setting"`
|
||||
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_user_setting"`
|
||||
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_user_setting"`
|
||||
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_user_setting"`
|
||||
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_user_setting"`
|
||||
}
|
||||
|
||||
func (m *LineUserSettingGetPageReq) GetNeedSearch() interface{} {
|
||||
return *m
|
||||
}
|
||||
|
||||
type LineUserSettingInsertReq struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount" comment:"单笔最小金额"`
|
||||
SpotUsdtFreeAmount decimal.Decimal `json:"spotUsdtFreeAmount" comment:"现货USDT可用余额"`
|
||||
FutureUsdtFreeAmount decimal.Decimal `json:"futureUsdtFreeAmount" comment:"合约USDT可用余额"`
|
||||
AssetUpdateTime time.Time `json:"assetUpdateTime" comment:"资产更新时间"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *LineUserSettingInsertReq) Generate(model *models.LineUserSetting) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.MinOrderAmount = s.MinOrderAmount
|
||||
model.SpotUsdtFreeAmount = s.SpotUsdtFreeAmount
|
||||
model.FutureUsdtFreeAmount = s.FutureUsdtFreeAmount
|
||||
model.AssetUpdateTime = &s.AssetUpdateTime
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
}
|
||||
|
||||
func (s *LineUserSettingInsertReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
type LineUserSettingUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键"` // 主键
|
||||
MinOrderAmount decimal.Decimal `json:"minOrderAmount" comment:"单笔最小金额"`
|
||||
SpotUsdtFreeAmount decimal.Decimal `json:"spotUsdtFreeAmount" comment:"现货USDT可用余额"`
|
||||
FutureUsdtFreeAmount decimal.Decimal `json:"futureUsdtFreeAmount" comment:"合约USDT可用余额"`
|
||||
AssetUpdateTime time.Time `json:"assetUpdateTime" comment:"资产更新时间"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *LineUserSettingUpdateReq) Generate(model *models.LineUserSetting) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.MinOrderAmount = s.MinOrderAmount
|
||||
model.SpotUsdtFreeAmount = s.SpotUsdtFreeAmount
|
||||
model.FutureUsdtFreeAmount = s.FutureUsdtFreeAmount
|
||||
model.AssetUpdateTime = &s.AssetUpdateTime
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
}
|
||||
|
||||
func (s *LineUserSettingUpdateReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
// LineUserSettingGetReq 功能获取请求参数
|
||||
type LineUserSettingGetReq struct {
|
||||
Id int `uri:"id"`
|
||||
}
|
||||
|
||||
func (s *LineUserSettingGetReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
// LineUserSettingDeleteReq 功能删除请求参数
|
||||
type LineUserSettingDeleteReq struct {
|
||||
Ids []int `json:"ids"`
|
||||
}
|
||||
|
||||
func (s *LineUserSettingDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
@ -41,7 +41,7 @@ func (s *MemberBalanceInsertReq) Generate(model *models.MemberBalance) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.TotalAmont = s.TotalAmont
|
||||
model.TotalAmount = s.TotalAmont
|
||||
model.FreeAmount = s.FreeAmount
|
||||
model.FrozenAmount = s.FrozenAmount
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
@ -63,7 +63,7 @@ func (s *MemberBalanceUpdateReq) Generate(model *models.MemberBalance) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.TotalAmont = s.TotalAmont
|
||||
model.TotalAmount = s.TotalAmont
|
||||
model.FreeAmount = s.FreeAmount
|
||||
model.FrozenAmount = s.FrozenAmount
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberBalanceLogGetPageReq struct {
|
||||
@ -15,7 +16,7 @@ type MemberBalanceLogGetPageReq struct {
|
||||
}
|
||||
|
||||
type MemberBalanceLogOrder struct {
|
||||
Id string `form:"idOrder" search:"type:order;column:id;table:member_balance_log"`
|
||||
Id string `form:"idOrder" query:"idOrder" search:"type:order;column:id;table:member_balance_log"`
|
||||
UserId string `form:"userIdOrder" search:"type:order;column:user_id;table:member_balance_log"`
|
||||
ChangeSource string `form:"changeSourceOrder" search:"type:order;column:change_source;table:member_balance_log"`
|
||||
ChangeType string `form:"changeTypeOrder" search:"type:order;column:change_type;table:member_balance_log"`
|
||||
@ -28,7 +29,6 @@ type MemberBalanceLogOrder struct {
|
||||
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:member_balance_log"`
|
||||
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:member_balance_log"`
|
||||
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:member_balance_log"`
|
||||
|
||||
}
|
||||
|
||||
func (m *MemberBalanceLogGetPageReq) GetNeedSearch() interface{} {
|
||||
@ -39,17 +39,17 @@ type MemberBalanceLogInsertReq struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
UserId int `json:"userId" comment:"用户id"`
|
||||
ChangeSource string `json:"changeSource" comment:"变更来源 (member_change_source)"`
|
||||
ChangeType string `json:"changeType" comment:"变更类别 1-收入 2-支出"`
|
||||
Amount string `json:"amount" comment:"变更金额"`
|
||||
BalanceBefore string `json:"balanceBefore" comment:"变更前余额"`
|
||||
BalanceAfter string `json:"balanceAfter" comment:"变更后余额"`
|
||||
ChangeType int `json:"changeType" comment:"变更类别 1-收入 2-支出"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"变更金额"`
|
||||
BalanceBefore decimal.Decimal `json:"balanceBefore" comment:"变更前余额"`
|
||||
BalanceAfter decimal.Decimal `json:"balanceAfter" comment:"变更后余额"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *MemberBalanceLogInsertReq) Generate(model *models.MemberBalanceLog) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{ Id: s.Id }
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.UserId = s.UserId
|
||||
model.ChangeSource = s.ChangeSource
|
||||
@ -69,17 +69,17 @@ type MemberBalanceLogUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键"` // 主键
|
||||
UserId int `json:"userId" comment:"用户id"`
|
||||
ChangeSource string `json:"changeSource" comment:"变更来源 (member_change_source)"`
|
||||
ChangeType string `json:"changeType" comment:"变更类别 1-收入 2-支出"`
|
||||
Amount string `json:"amount" comment:"变更金额"`
|
||||
BalanceBefore string `json:"balanceBefore" comment:"变更前余额"`
|
||||
BalanceAfter string `json:"balanceAfter" comment:"变更后余额"`
|
||||
ChangeType int `json:"changeType" comment:"变更类别 1-收入 2-支出"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"变更金额"`
|
||||
BalanceBefore decimal.Decimal `json:"balanceBefore" comment:"变更前余额"`
|
||||
BalanceAfter decimal.Decimal `json:"balanceAfter" comment:"变更后余额"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *MemberBalanceLogUpdateReq) Generate(model *models.MemberBalanceLog) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{ Id: s.Id }
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.UserId = s.UserId
|
||||
model.ChangeSource = s.ChangeSource
|
||||
@ -99,6 +99,7 @@ func (s *MemberBalanceLogUpdateReq) GetId() interface{} {
|
||||
type MemberBalanceLogGetReq struct {
|
||||
Id int `uri:"id"`
|
||||
}
|
||||
|
||||
func (s *MemberBalanceLogGetReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
@ -111,3 +112,28 @@ type MemberBalanceLogDeleteReq struct {
|
||||
func (s *MemberBalanceLogDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
|
||||
type MemberBalanceLogPageAppReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
ChangeSource string `form:"changeSource" search:"type:exact;column:change_source;table:member_balance_log" comment:"变更来源 (member_change_source)"`
|
||||
ChangeType string `form:"changeType" search:"type:exact;column:change_type;table:member_balance_log" comment:"变更类别 1-收入 2-支出"`
|
||||
UserId int `json:"userId" search:"-"`
|
||||
Language string `json:"language" search:"-"`
|
||||
MemberBalanceLogOrder
|
||||
}
|
||||
|
||||
func (m *MemberBalanceLogPageAppReq) GetNeedSearch() interface{} {
|
||||
return *m
|
||||
}
|
||||
|
||||
type MemberBalanceLogAppResp struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
UserId int `json:"userId" comment:"用户id"`
|
||||
UserName string `json:"userName" comment:"用户名"`
|
||||
ChangeSource string `json:"changeSource" comment:"变更来源 (member_change_source)"`
|
||||
ChangeSourceName string `json:"changeSourceName"`
|
||||
ChangeType int `json:"changeType" comment:"变更类别 1-收入 2-支出"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"变更金额"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
CreateTimeUnix int64 `json:"createTime" comment:"创建时间"`
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberRenwaLogGetPageReq struct {
|
||||
@ -15,18 +17,28 @@ type MemberRenwaLogGetPageReq struct {
|
||||
|
||||
type MemberRenwalLogPageAppReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
Language string `search:"-"`
|
||||
MemberRenwaLogOrder
|
||||
}
|
||||
|
||||
func (m *MemberRenwalLogPageAppReq) GetNeedSearch() interface{} {
|
||||
return *m
|
||||
}
|
||||
|
||||
type MemberRenwalLogResp struct {
|
||||
Id int `json:"id"`
|
||||
NetworkName string `json:"networkName"`
|
||||
ReceiveAddress string `json:"receiveAddress"`
|
||||
RenwalName string `json:"renwalName" comment:"续期套餐名称"`
|
||||
RenwalDuration string `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
RenwalDuration int `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
Status string `json:"status" comment:"订单状态(member_renwal_log_status)"`
|
||||
PayableAmount string `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount string `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
StatusLabel string `json:"statusLabel"`
|
||||
PayableAmount decimal.Decimal `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount decimal.Decimal `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
FromAddress string `json:"fromAddress" comment:"付款地址"`
|
||||
Coin string `json:"coin" comment:"代币"`
|
||||
PaymentTime time.Time `json:"paymentTime" comment:"支付时间"`
|
||||
PaymentTimeUnix int64 `json:"paymentTimeUnix" comment:"支付时间"`
|
||||
ExpirationTimeUnix int64 `json:"expirationTimeUnix" comment:"过期时间"`
|
||||
}
|
||||
|
||||
type MemberRenwaLogOrder struct {
|
||||
@ -53,12 +65,12 @@ func (m *MemberRenwaLogGetPageReq) GetNeedSearch() interface{} {
|
||||
|
||||
type MemberRenwaLogInsertReq struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
RenwalId string `json:"renwalId" comment:"套餐id"`
|
||||
RenwalId int `json:"renwalId" comment:"套餐id"`
|
||||
RenwalName string `json:"renwalName" comment:"续期套餐名称"`
|
||||
RenwalDuration string `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
RenwalDuration int `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
Status string `json:"status" comment:"订单状态(member_renwal_log_status)"`
|
||||
PayableAmount string `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount string `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
PayableAmount decimal.Decimal `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount decimal.Decimal `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
FromAddress string `json:"fromAddress" comment:"付款地址"`
|
||||
Coin string `json:"coin" comment:"代币"`
|
||||
PaymentTime time.Time `json:"paymentTime" comment:"支付时间"`
|
||||
@ -77,7 +89,7 @@ func (s *MemberRenwaLogInsertReq) Generate(model *models.MemberRenwaLog) {
|
||||
model.ActualPaymentAmount = s.ActualPaymentAmount
|
||||
model.FromAddress = s.FromAddress
|
||||
model.Coin = s.Coin
|
||||
model.PaymentTime = s.PaymentTime
|
||||
// model.PaymentTime = s.PaymentTime
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
}
|
||||
|
||||
@ -87,15 +99,15 @@ func (s *MemberRenwaLogInsertReq) GetId() interface{} {
|
||||
|
||||
type MemberRenwaLogUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键"` // 主键
|
||||
RenwalId string `json:"renwalId" comment:"套餐id"`
|
||||
RenwalId int `json:"renwalId" comment:"套餐id"`
|
||||
RenwalName string `json:"renwalName" comment:"续期套餐名称"`
|
||||
RenwalDuration string `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
RenwalDuration int `json:"renwalDuration" comment:"续期时长(天数)"`
|
||||
Status string `json:"status" comment:"订单状态(member_renwal_log_status)"`
|
||||
PayableAmount string `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount string `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
PayableAmount decimal.Decimal `json:"payableAmount" comment:"应付金额"`
|
||||
ActualPaymentAmount decimal.Decimal `json:"actualPaymentAmount" comment:"实付金额"`
|
||||
FromAddress string `json:"fromAddress" comment:"付款地址"`
|
||||
Coin string `json:"coin" comment:"代币"`
|
||||
PaymentTime time.Time `json:"paymentTime" comment:"支付时间"`
|
||||
// PaymentTime time.Time `json:"paymentTime" comment:"支付时间"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
@ -111,7 +123,7 @@ func (s *MemberRenwaLogUpdateReq) Generate(model *models.MemberRenwaLog) {
|
||||
model.ActualPaymentAmount = s.ActualPaymentAmount
|
||||
model.FromAddress = s.FromAddress
|
||||
model.Coin = s.Coin
|
||||
model.PaymentTime = s.PaymentTime
|
||||
// model.PaymentTime = s.PaymentTime
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
}
|
||||
|
||||
@ -136,3 +148,15 @@ type MemberRenwaLogDeleteReq struct {
|
||||
func (s *MemberRenwaLogDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
|
||||
type MemberRenwalCreateAppReq struct {
|
||||
ConfigId int `json:"configId"`
|
||||
UserId int `json:"-"`
|
||||
}
|
||||
|
||||
type MemberRenwalCreateAppResp struct {
|
||||
NetworkName string `json:"networkName"` //网络名称
|
||||
Amount decimal.Decimal `json:"amount"`
|
||||
ToAddress string `json:"toAddress"` //收款地址
|
||||
ExpirationTimeUnix int64 `json:"expirationTimeUnix"` //过期时间
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
@ -38,6 +39,7 @@ func (m *MemberRenwalConfigGetPageReq) GetNeedSearch() interface{} {
|
||||
type MemberRenwalConfigInsertReq struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
PackageName string `json:"packageName" comment:"套餐名称"`
|
||||
PackageNameEn string `json:"packageNameEn" comment:"套餐名称英文"`
|
||||
DurationDay int `json:"durationDay" comment:"续期时间(天)"`
|
||||
OriginalPrice decimal.Decimal `json:"originalPrice" comment:"原始单价"`
|
||||
DiscountPrice *decimal.Decimal `json:"discountPrice" comment:"折扣价格 -1为未设置"`
|
||||
@ -49,11 +51,29 @@ type MemberRenwalConfigInsertReq struct {
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (s *MemberRenwalConfigInsertReq) Valid() error {
|
||||
if s.PackageName == "" {
|
||||
return errors.New("套餐名称不能为空")
|
||||
}
|
||||
|
||||
if s.PackageNameEn == "" {
|
||||
return errors.New("套餐名称英文不能为空")
|
||||
}
|
||||
|
||||
if s.DurationDay <= 0 {
|
||||
return errors.New("续期时间(天)不能为空")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MemberRenwalConfigInsertReq) Generate(model *models.MemberRenwalConfig) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.PackageName = s.PackageName
|
||||
model.PackageNameEn = s.PackageNameEn
|
||||
model.DurationDay = s.DurationDay
|
||||
model.OriginalPrice = s.OriginalPrice
|
||||
|
||||
@ -77,6 +97,7 @@ func (s *MemberRenwalConfigInsertReq) GetId() interface{} {
|
||||
type MemberRenwalConfigUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键"` // 主键
|
||||
PackageName string `json:"packageName" comment:"套餐名称"`
|
||||
PackageNameEn string `json:"packageNameEn" comment:"套餐名称英文"`
|
||||
DurationDay int `json:"durationDay" comment:"续期时间(天)"`
|
||||
OriginalPrice decimal.Decimal `json:"originalPrice" comment:"原始单价"`
|
||||
DiscountPrice *decimal.Decimal `json:"discountPrice" comment:"折扣价格 -1为未设置"`
|
||||
@ -88,11 +109,29 @@ type MemberRenwalConfigUpdateReq struct {
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
// 校验
|
||||
func (s *MemberRenwalConfigUpdateReq) Valid() error {
|
||||
if s.PackageName == "" {
|
||||
return errors.New("套餐名称不能为空")
|
||||
}
|
||||
|
||||
if s.PackageNameEn == "" {
|
||||
return errors.New("套餐名称英文不能为空")
|
||||
}
|
||||
|
||||
if s.DurationDay <= 0 {
|
||||
return errors.New("续期时间(天)不能为空")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MemberRenwalConfigUpdateReq) Generate(model *models.MemberRenwalConfig) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.PackageName = s.PackageName
|
||||
model.PackageNameEn = s.PackageNameEn
|
||||
model.DurationDay = s.DurationDay
|
||||
model.OriginalPrice = s.OriginalPrice
|
||||
|
||||
@ -130,3 +169,12 @@ type MemberRenwalConfigDeleteReq struct {
|
||||
func (s *MemberRenwalConfigDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
|
||||
type MemberRenwalConfigAppResp struct {
|
||||
Id int `json:"id" comment:"主键"` // 主键
|
||||
PackageName string `json:"packageName" comment:"套餐名称"`
|
||||
DurationDay int `json:"durationDay" comment:"续期时间(天)"`
|
||||
OriginalPrice decimal.Decimal `json:"originalPrice" comment:"原始单价"`
|
||||
DiscountPrice decimal.Decimal `json:"discountPrice" comment:"折扣价格 -1为未设置"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
}
|
||||
|
||||
198
app/admin/service/dto/member_withdrawal_log.go
Normal file
198
app/admin/service/dto/member_withdrawal_log.go
Normal file
@ -0,0 +1,198 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
statuscode "go-admin/common/status_code"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLogGetPageReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
NetworkName string `form:"networkName" search:"type:contains;column:network_name;table:member_withdrawal_log" comment:"网络名称"`
|
||||
Status string `form:"status" search:"type:exact;column:status;table:member_withdrawal_log" comment:"提现状态(member_withdrawal_status)"`
|
||||
MemberWithdrawalLogOrder
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogGetPageAppReq struct {
|
||||
dto.Pagination `search:"-"`
|
||||
NetworkName string `form:"networkName" search:"type:contains;column:network_name;table:member_withdrawal_log" comment:"网络名称"`
|
||||
Status string `form:"status" search:"type:exact;column:status;table:member_withdrawal_log" comment:"提现状态(member_withdrawal_status)"`
|
||||
UserId int `form:"userId" search:"type:exact;column:user_id;table:member_withdrawal_log" comment:"用户id"`
|
||||
|
||||
MemberWithdrawalLogOrder
|
||||
}
|
||||
|
||||
func (m *MemberWithdrawalLogGetPageAppReq) GetNeedSearch() interface{} {
|
||||
return *m
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogOrder struct {
|
||||
Id string `form:"idOrder" search:"type:order;column:id;table:member_withdrawal_log"`
|
||||
NetworkId string `form:"networkIdOrder" search:"type:order;column:network_id;table:member_withdrawal_log"`
|
||||
NetworkName string `form:"networkNameOrder" search:"type:order;column:network_name;table:member_withdrawal_log"`
|
||||
UserId string `form:"userIdOrder" search:"type:order;column:user_id;table:member_withdrawal_log"`
|
||||
Amount string `form:"amountOrder" search:"type:order;column:amount;table:member_withdrawal_log"`
|
||||
Status string `form:"statusOrder" search:"type:order;column:status;table:member_withdrawal_log"`
|
||||
ConfirmTime string `form:"confirmTimeOrder" search:"type:order;column:confirm_time;table:member_withdrawal_log"`
|
||||
Fee string `form:"feeOrder" search:"type:order;column:fee;table:member_withdrawal_log"`
|
||||
Remark string `form:"remarkOrder" search:"type:order;column:remark;table:member_withdrawal_log"`
|
||||
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:member_withdrawal_log"`
|
||||
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:member_withdrawal_log"`
|
||||
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:member_withdrawal_log"`
|
||||
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:member_withdrawal_log"`
|
||||
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:member_withdrawal_log"`
|
||||
}
|
||||
|
||||
func (m *MemberWithdrawalLogGetPageReq) GetNeedSearch() interface{} {
|
||||
return *m
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogInsertReq struct {
|
||||
Id int `json:"-" comment:"主键"` // 主键
|
||||
NetworkId int `json:"networkId" comment:"网络id"`
|
||||
NetworkName string `json:"networkName" comment:"网络名称"`
|
||||
UserId int `json:"userId" comment:"用户id"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"提现金额(U)"`
|
||||
Status string `json:"status" comment:"提现状态(member_withdrawal_status)"`
|
||||
ConfirmTime *time.Time `json:"confirmTime" comment:"确认时间"`
|
||||
Fee decimal.Decimal `json:"fee" comment:"手续费比例"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogInsertReq) Generate(model *models.MemberWithdrawalLog) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.NetworkId = s.NetworkId
|
||||
model.NetworkName = s.NetworkName
|
||||
model.UserId = s.UserId
|
||||
model.Amount = s.Amount
|
||||
model.Status = s.Status
|
||||
model.ConfirmTime = s.ConfirmTime
|
||||
model.Fee = s.Fee
|
||||
model.Remark = s.Remark
|
||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogInsertReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogUpdateReq struct {
|
||||
Id int `uri:"id" comment:"主键"` // 主键
|
||||
NetworkId int `json:"networkId" comment:"网络id"`
|
||||
NetworkName string `json:"networkName" comment:"网络名称"`
|
||||
UserId int `json:"userId" comment:"用户id"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"提现金额(U)"`
|
||||
Status string `json:"status" comment:"提现状态(member_withdrawal_status)"`
|
||||
ConfirmTime *time.Time `json:"confirmTime" comment:"确认时间"`
|
||||
Fee decimal.Decimal `json:"fee" comment:"手续费比例"`
|
||||
Remark string `json:"remark" comment:"备注"`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogUpdateReq) Generate(model *models.MemberWithdrawalLog) {
|
||||
if s.Id == 0 {
|
||||
model.Model = common.Model{Id: s.Id}
|
||||
}
|
||||
model.NetworkId = s.NetworkId
|
||||
model.NetworkName = s.NetworkName
|
||||
model.UserId = s.UserId
|
||||
model.Amount = s.Amount
|
||||
model.Status = s.Status
|
||||
model.ConfirmTime = s.ConfirmTime
|
||||
model.Fee = s.Fee
|
||||
model.Remark = s.Remark
|
||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogUpdateReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
// MemberWithdrawalLogGetReq 功能获取请求参数
|
||||
type MemberWithdrawalLogGetReq struct {
|
||||
Id int `uri:"id"`
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogGetReq) GetId() interface{} {
|
||||
return s.Id
|
||||
}
|
||||
|
||||
// MemberWithdrawalLogDeleteReq 功能删除请求参数
|
||||
type MemberWithdrawalLogDeleteReq struct {
|
||||
Ids []int `json:"ids"`
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogCancelReq struct {
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
func (s *MemberWithdrawalLogCancelReq) Valid() int {
|
||||
if s.Id <= 0 {
|
||||
return statuscode.ParamErr
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogApplyReq struct {
|
||||
NetworkId int `json:"networkId" comment:"网络ID"`
|
||||
UserId int `json:"userId" comment:"用户ID"`
|
||||
Amount decimal.Decimal `json:"amount" comment:"提现金额"`
|
||||
ToAddress string `json:"toAddress" comment:"提现地址"`
|
||||
}
|
||||
|
||||
func (e *MemberWithdrawalLogApplyReq) Valid() int {
|
||||
if e.NetworkId <= 0 {
|
||||
return statuscode.ParamErr
|
||||
}
|
||||
|
||||
if e.Amount.Cmp(decimal.Zero) <= 0 {
|
||||
return statuscode.ParamErr
|
||||
}
|
||||
|
||||
if e.ToAddress == "" {
|
||||
return statuscode.ParamErr
|
||||
}
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogResp struct {
|
||||
Id int `json:"id"`
|
||||
NetworkId int `json:"networkId"`
|
||||
NetworkName string `json:"networkName"`
|
||||
UserId int `json:"userId"`
|
||||
NickName string `json:"nickName"`
|
||||
Amount decimal.Decimal `json:"amount"`
|
||||
Fee decimal.Decimal `json:"fee"`
|
||||
ToAddress string `json:"toAddress"`
|
||||
Hash string `json:"hash"`
|
||||
Status string `json:"status"`
|
||||
CreateTimeUnix int64 `json:"createTime"`
|
||||
ConfirmTimeUnix int64 `json:"confirmTime"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogApprovedReq struct {
|
||||
Id int `json:"id"`
|
||||
Approval int `json:"approval"` // 1:通过 2:拒绝
|
||||
Remark string `json:"remark" comment:"备注" `
|
||||
}
|
||||
|
||||
type MemberWithdrawalLogConfirmReq struct {
|
||||
Id int `json:"id"`
|
||||
ConfirmVal int `json:"confirmVal"` // 1:成功 2:失败
|
||||
Remark string `json:"remark"`
|
||||
Hash string `json:"hash"` //交易hash
|
||||
}
|
||||
@ -115,3 +115,11 @@ type SameSymbol struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Number int `json:"number"`
|
||||
}
|
||||
|
||||
type FrontedDefaultSetResp struct {
|
||||
MinOrderAmount string `json:"minOrderAmount"`
|
||||
BinanceReferralLink string `json:"binanceReferralLink"`
|
||||
BinanceReferralCode string `json:"binanceReferalCode"`
|
||||
CustomServiceLink string `json:"customServiceLink"`
|
||||
TelegramLink string `json:"telegramLink"`
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import (
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/common/dto"
|
||||
common "go-admin/common/models"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
)
|
||||
|
||||
type SysDictDataGetPageReq struct {
|
||||
@ -25,6 +27,7 @@ type SysDictDataGetAllResp struct {
|
||||
}
|
||||
|
||||
type SysDictDataResp struct {
|
||||
DictCode int `json:"dictCode"`
|
||||
DictSort int `json:"dictSort" comment:""`
|
||||
DictLabel string `json:"dictLabel" comment:""`
|
||||
DictValue string `json:"dictValue" comment:""`
|
||||
@ -35,6 +38,7 @@ type SysDictDataResp struct {
|
||||
Status int `json:"status" comment:""`
|
||||
Default string `json:"default" comment:""`
|
||||
Remark string `json:"remark" comment:""`
|
||||
LanguageData []SysDictDataLanguageData `json:"languageData"`
|
||||
}
|
||||
type SysDictDataInsertReq struct {
|
||||
Id int `json:"-" comment:""`
|
||||
@ -48,6 +52,7 @@ type SysDictDataInsertReq struct {
|
||||
Status int `json:"status" comment:""`
|
||||
Default string `json:"default" comment:""`
|
||||
Remark string `json:"remark" comment:""`
|
||||
LanguageData []SysDictDataLanguageData `json:"languageData" comment:""`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
@ -63,6 +68,7 @@ func (s *SysDictDataInsertReq) Generate(model *models.SysDictData) {
|
||||
model.Status = s.Status
|
||||
model.Default = s.Default
|
||||
model.Remark = s.Remark
|
||||
model.Language, _ = sonic.MarshalString(s.LanguageData)
|
||||
}
|
||||
|
||||
func (s *SysDictDataInsertReq) GetId() interface{} {
|
||||
@ -81,6 +87,7 @@ type SysDictDataUpdateReq struct {
|
||||
Status int `json:"status" comment:""`
|
||||
Default string `json:"default" comment:""`
|
||||
Remark string `json:"remark" comment:""`
|
||||
LanguageData []SysDictDataLanguageData `json:"languageData" comment:""`
|
||||
common.ControlBy
|
||||
}
|
||||
|
||||
@ -96,6 +103,7 @@ func (s *SysDictDataUpdateReq) Generate(model *models.SysDictData) {
|
||||
model.Status = s.Status
|
||||
model.Default = s.Default
|
||||
model.Remark = s.Remark
|
||||
model.Language, _ = sonic.MarshalString(s.LanguageData)
|
||||
}
|
||||
|
||||
func (s *SysDictDataUpdateReq) GetId() interface{} {
|
||||
@ -118,3 +126,8 @@ type SysDictDataDeleteReq struct {
|
||||
func (s *SysDictDataDeleteReq) GetId() interface{} {
|
||||
return s.Ids
|
||||
}
|
||||
|
||||
type SysDictDataLanguageData struct {
|
||||
Key string `json:"k"` //多语言键
|
||||
Value string `json:"v"`
|
||||
}
|
||||
|
||||
@ -64,6 +64,13 @@ func (e *LineCoinnetwork) Insert(c *dto.LineCoinnetworkInsertReq) error {
|
||||
var err error
|
||||
var data models.LineCoinnetwork
|
||||
c.Generate(&data)
|
||||
var count int64
|
||||
e.Orm.Model(&data).Where("network_name =?").Count(&count)
|
||||
|
||||
if count > 0 {
|
||||
return errors.New("网络已存在")
|
||||
}
|
||||
|
||||
err = e.Orm.Create(&data).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("LineCoinnetworkService Insert error:%s \r\n", err)
|
||||
@ -76,6 +83,13 @@ func (e *LineCoinnetwork) Insert(c *dto.LineCoinnetworkInsertReq) error {
|
||||
func (e *LineCoinnetwork) Update(c *dto.LineCoinnetworkUpdateReq, p *actions.DataPermission) error {
|
||||
var err error
|
||||
var data = models.LineCoinnetwork{}
|
||||
var count int64
|
||||
e.Orm.Model(&data).Where("network_name =? AND id !=?", c.NetworkName, c.Id).Count(&count)
|
||||
|
||||
if count > 0 {
|
||||
return errors.New("网络已存在")
|
||||
}
|
||||
|
||||
e.Orm.Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).First(&data, c.GetId())
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -294,17 +294,14 @@ func (e *LineSymbol) ResetSpotSymbol() error {
|
||||
logger.Error("获取币安现货交易对失败")
|
||||
return err
|
||||
}
|
||||
symbols := make([]models.LineSymbol, 0)
|
||||
|
||||
insertSymbols := make([]models.LineSymbol, 0)
|
||||
sysConfig := SysConfig{Service: service.Service{Orm: e.Orm}}
|
||||
|
||||
var req = new(dto.SysConfigByKeyReq)
|
||||
var resp = new(dto.GetSysConfigByKEYForServiceResp)
|
||||
req.ConfigKey = "quote_volume_24hr"
|
||||
sysConfig.GetWithKey(req, resp)
|
||||
symbolBlack := make([]models.LineSymbolBlack, 0)
|
||||
e.Orm.Model(&models.LineSymbolBlack{}).Where("type = '1'").Find(&symbolBlack)
|
||||
|
||||
symbolBlackMap := getSymbolBlackMap(e, "1")
|
||||
type Ticker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price string `json:"price"`
|
||||
@ -317,18 +314,17 @@ func (e *LineSymbol) ResetSpotSymbol() error {
|
||||
return err
|
||||
}
|
||||
|
||||
//判断是否在黑名单、是否需要修改
|
||||
for symbol, tradeSet := range tradeSets {
|
||||
|
||||
key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbol)
|
||||
|
||||
//判断是否在黑名单里面
|
||||
for _, black := range symbolBlack {
|
||||
if black.Symbol == symbol {
|
||||
if _, ok := symbolBlackMap[symbol]; ok {
|
||||
helper.DefaultRedis.DeleteString(key)
|
||||
deleteSymbols = append(deleteSymbols, symbol)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val := helper.DefaultRedis.Get(key).Val()
|
||||
var spotTicker24h commonModels.TradeSet
|
||||
@ -369,7 +365,14 @@ func (e *LineSymbol) ResetSpotSymbol() error {
|
||||
if lineSymbol.Symbol == "" {
|
||||
continue
|
||||
}
|
||||
symbols = append(symbols, lineSymbol)
|
||||
insertSymbols = append(insertSymbols, lineSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
//判断已经移除的交易对
|
||||
for _, v := range oldMapSymbols {
|
||||
if _, ok := tradeSets[v.Symbol]; !ok && !utility.ContainsStr(deleteSymbols, v.Symbol) {
|
||||
deleteSymbols = append(deleteSymbols, v.Symbol)
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,8 +396,8 @@ func (e *LineSymbol) ResetSpotSymbol() error {
|
||||
batchDeleteBySymbols(deleteSymbols, "1", e)
|
||||
}
|
||||
|
||||
if len(symbols) > 0 {
|
||||
err := e.Orm.Model(&models.LineSymbol{}).Omit("api_id").Create(&symbols).Error
|
||||
if len(insertSymbols) > 0 {
|
||||
err := e.Orm.Model(&models.LineSymbol{}).Omit("api_id").Create(&insertSymbols).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -403,6 +406,18 @@ func (e *LineSymbol) ResetSpotSymbol() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSymbolBlackMap(e *LineSymbol, symbolType string) map[string]models.LineSymbolBlack {
|
||||
symbolBlack := make([]models.LineSymbolBlack, 0)
|
||||
symbolBlackMap := make(map[string]models.LineSymbolBlack)
|
||||
|
||||
e.Orm.Model(&models.LineSymbolBlack{}).Where("type = ?", symbolType).Find(&symbolBlack)
|
||||
|
||||
for _, v := range symbolBlack {
|
||||
symbolBlackMap[v.Symbol] = v
|
||||
}
|
||||
return symbolBlackMap
|
||||
}
|
||||
|
||||
// 批量删除 根据交易对名
|
||||
// symbolType 1-现货 2-合约
|
||||
func batchDeleteBySymbols(deleteSymbols []string, symbolType string, e *LineSymbol) {
|
||||
@ -459,8 +474,7 @@ func (e *LineSymbol) ResetFuturesSymbol() error {
|
||||
req.ConfigKey = "quote_volume_24hr"
|
||||
sysConfig.GetWithKey(req, resp)
|
||||
symbols := make([]models.LineSymbol, 0)
|
||||
symbolBlack := make([]models.LineSymbolBlack, 0)
|
||||
|
||||
symbolBlackMap := getSymbolBlackMap(e, "2")
|
||||
type Ticker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price string `json:"price"`
|
||||
@ -473,19 +487,17 @@ func (e *LineSymbol) ResetFuturesSymbol() error {
|
||||
return err
|
||||
}
|
||||
|
||||
e.Orm.Model(&models.LineSymbolBlack{}).Where("type = 2").Find(&symbolBlack)
|
||||
//判断是否在黑名单、是否需要新增
|
||||
for symbol, tradeSet := range tradeSets {
|
||||
|
||||
key := fmt.Sprintf(global.TICKER_FUTURES, global.EXCHANGE_BINANCE, symbol)
|
||||
|
||||
//判断是否在黑名单里面
|
||||
for _, black := range symbolBlack {
|
||||
if black.Symbol == symbol {
|
||||
if _, ok := symbolBlackMap[symbol]; ok {
|
||||
helper.DefaultRedis.DeleteString(key)
|
||||
deleteSymbols = append(deleteSymbols, symbol)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val := helper.DefaultRedis.Get(key).Val()
|
||||
var spotTicker24h commonModels.TradeSet
|
||||
sonic.Unmarshal([]byte(val), &spotTicker24h)
|
||||
@ -528,6 +540,13 @@ func (e *LineSymbol) ResetFuturesSymbol() error {
|
||||
}
|
||||
}
|
||||
|
||||
//交易所已经没有的交易对直接去除
|
||||
for _, v := range oldMapSymbols {
|
||||
if _, ok := tradeSets[v.Symbol]; !ok && !utility.ContainsStr(deleteSymbols, v.Symbol) {
|
||||
deleteSymbols = append(deleteSymbols, v.Symbol)
|
||||
}
|
||||
}
|
||||
|
||||
groups, err := getSymbolGroups(e, "2")
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@ -79,15 +79,11 @@ func (e *LineSymbolBlack) Insert(c *dto.LineSymbolBlackInsertReq) error {
|
||||
}
|
||||
|
||||
err = e.Orm.Create(&data).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("LineSymbolBlackService Insert error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return e.reloadSymbol(c.Type)
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *LineSymbolBlack) reloadSymbol(symbolType string) error {
|
||||
func (e *LineSymbolBlack) ReloadSymbol(symbolType string) error {
|
||||
symbolService := LineSymbol{Service: e.Service}
|
||||
|
||||
if symbolType == "1" {
|
||||
@ -133,21 +129,12 @@ func (e *LineSymbolBlack) Update(c *dto.LineSymbolBlackUpdateReq, p *actions.Dat
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权更新该数据")
|
||||
}
|
||||
return e.reloadSymbol(c.Type)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 删除LineSymbolBlack
|
||||
func (e *LineSymbolBlack) Remove(d *dto.LineSymbolBlackDeleteReq, p *actions.DataPermission) error {
|
||||
var data models.LineSymbolBlack
|
||||
types := make([]string, 0)
|
||||
|
||||
e.Orm.Model(&data).Where("id in ?", d.GetId()).Select("type").Distinct().Find(&types)
|
||||
|
||||
for _, v := range types {
|
||||
if v != "" {
|
||||
e.reloadSymbol(v)
|
||||
}
|
||||
}
|
||||
|
||||
db := e.Orm.Model(&data).
|
||||
Scopes(
|
||||
|
||||
@ -6,11 +6,13 @@ import (
|
||||
"go-admin/common/const/rediskey"
|
||||
"go-admin/common/global"
|
||||
"go-admin/common/helper"
|
||||
"go-admin/common/service/sysservice/authservice"
|
||||
statuscode "go-admin/common/status_code"
|
||||
ext "go-admin/config"
|
||||
"go-admin/models/coingatedto"
|
||||
"go-admin/pkg/coingate"
|
||||
"go-admin/pkg/cryptohelper/aeshelper"
|
||||
"go-admin/pkg/cryptohelper/md5helper"
|
||||
"go-admin/pkg/timehelper"
|
||||
"go-admin/pkg/udunhelper"
|
||||
"go-admin/pkg/utility"
|
||||
@ -21,6 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/shopspring/decimal"
|
||||
"go.uber.org/zap"
|
||||
@ -40,6 +43,9 @@ type LineUser struct {
|
||||
func (e *LineUser) GetPage(c *dto.LineUserGetPageReq, p *actions.DataPermission, list *[]models.LineUser, count *int64) error {
|
||||
var err error
|
||||
var data models.LineUser
|
||||
userIds := make([]int, 0)
|
||||
apiUsers := make([]models.LineApiUser, 0)
|
||||
userSettings := make([]models.LineUserSetting, 0)
|
||||
|
||||
err = e.Orm.Model(&data).
|
||||
Scopes(
|
||||
@ -53,11 +59,37 @@ func (e *LineUser) GetPage(c *dto.LineUserGetPageReq, p *actions.DataPermission,
|
||||
e.Log.Errorf("LineUserService GetPage error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
for i, user := range *list {
|
||||
var apiUserinfo models.LineApiUser
|
||||
e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", user.Id).Find(&apiUserinfo)
|
||||
(*list)[i].OpenStatus = int(apiUserinfo.OpenStatus)
|
||||
for _, user := range *list {
|
||||
if utility.ContainsInt(userIds, user.Id) {
|
||||
continue
|
||||
}
|
||||
userIds = append(userIds, user.Id)
|
||||
}
|
||||
|
||||
if len(userIds) > 0 {
|
||||
e.Orm.Model(&models.LineApiUser{}).Where("user_id in (?)", userIds).Find(&apiUsers)
|
||||
e.Orm.Model(&models.LineUserSetting{}).Where("user_id in (?)", userIds).Find(&userSettings)
|
||||
}
|
||||
|
||||
for i := range *list {
|
||||
for _, item := range apiUsers {
|
||||
if item.UserId == int64((*list)[i].Id) {
|
||||
(*list)[i].OpenStatus = int(item.OpenStatus)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range userSettings {
|
||||
if item.UserId == (*list)[i].Id {
|
||||
(*list)[i].SpotFreeAmount = item.SpotUsdtFreeAmount
|
||||
(*list)[i].FutureFreeAmount = item.FutureUsdtFreeAmount
|
||||
(*list)[i].MinOrderAmount = item.MinOrderAmount
|
||||
(*list)[i].AssetUpdateTime = item.AssetUpdateTime
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -491,6 +523,7 @@ func (e *LineUser) PreOrder(userId int, req *dto.VtsRechargePreOrderReq, resp *d
|
||||
return nil
|
||||
}
|
||||
|
||||
// 模拟支付回调
|
||||
func (e *LineUser) CallBack(req *coingatedto.OrderCallBackResponse) error {
|
||||
token, err := aeshelper.PswEncrypt(fmt.Sprintf("%s:%s:%s", req.OrderID, utility.StringAsDecimal(req.PriceAmount), req.PriceCurrency))
|
||||
|
||||
@ -562,3 +595,164 @@ func (e *LineUser) CallBack(req *coingatedto.OrderCallBackResponse) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取用户资产
|
||||
func (e *LineUser) GetProperty(userId int, data *dto.LineUserPropertyResp) int {
|
||||
lineApiUser := models.LineApiUser{}
|
||||
|
||||
if err := e.Orm.Model(&lineApiUser).Where("user_id=?", userId).First(&lineApiUser).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.UserApiUserNotBind
|
||||
}
|
||||
logger.Errorf("用户id %v 获取api用户失败:%v", userId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
binanceservice.GetSpotUProperty(lineApiUser, data)
|
||||
binanceservice.GetFuturesUProperty(lineApiUser, data)
|
||||
|
||||
userSetting := models.LineUserSetting{}
|
||||
e.Orm.Model(&userSetting).Where("user_id=?", userId).First(&userSetting)
|
||||
|
||||
if userSetting.Id > 0 {
|
||||
userSetting.SpotUsdtFreeAmount = data.SpotFreeAmount
|
||||
userSetting.FutureUsdtFreeAmount = data.FuturesFreeAmount
|
||||
|
||||
if err := e.Orm.Model(&userSetting).Updates(map[string]interface{}{"spot_usdt_free_amount": data.SpotFreeAmount, "future_usdt_free_amount": data.FuturesFreeAmount, "asset_update_time": time.Now()}).Error; err != nil {
|
||||
logger.Errorf("用户id %v 更新用户资产失败:%v", userId, err)
|
||||
}
|
||||
} else {
|
||||
now := time.Now()
|
||||
userSetting.UserId = userId
|
||||
userSetting.SpotUsdtFreeAmount = data.SpotFreeAmount
|
||||
userSetting.FutureUsdtFreeAmount = data.FuturesFreeAmount
|
||||
userSetting.AssetUpdateTime = &now
|
||||
|
||||
if err := e.Orm.Create(&userSetting).Error; err != nil {
|
||||
logger.Errorf("用户id %v 创建用户资产失败:%v", userId, err)
|
||||
}
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
// 设置用户下单配置
|
||||
// return statuscode
|
||||
func (e *LineUser) OrderSet(req *dto.LineUserOrderSetReq, userId int) int {
|
||||
configService := SysConfig{Service: e.Service}
|
||||
configResp := dto.GetSysConfigByKEYForServiceResp{}
|
||||
|
||||
configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "member_min_order_amount"}, &configResp)
|
||||
minOrderAmount := utility.StrToDecimal(configResp.ConfigValue)
|
||||
|
||||
if req.MinOrderAmount.Cmp(minOrderAmount) < 0 {
|
||||
return statuscode.MemberMinOrderAmountLessMininum
|
||||
}
|
||||
|
||||
userSet := models.LineUserSetting{}
|
||||
e.Orm.Model(&userSet).Where("user_id =?", userId).Find(&userSet)
|
||||
|
||||
if userSet.Id > 0 {
|
||||
if err := e.Orm.Model(&userSet).Update("min_order_amount", req.MinOrderAmount).Error; err != nil {
|
||||
logger.Errorf("用户id %v 更新api用户下单配置失败:%v", userId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
} else {
|
||||
userSet.UserId = userId
|
||||
userSet.MinOrderAmount = req.MinOrderAmount
|
||||
if err := e.Orm.Create(&userSet).Error; err != nil {
|
||||
logger.Errorf("用户id %v 创建api用户下单配置失败:%v", userId, err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
func (e *LineUser) ResetPassword(req *dto.LineUserResetPwdReq) int {
|
||||
user := models.LineUser{}
|
||||
status := statuscode.OK
|
||||
|
||||
switch req.Type {
|
||||
case 1:
|
||||
if err := e.Orm.Model(&user).Where("mobile =? AND area= ?", req.Phone, req.PhoneAreaCode).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.DataError
|
||||
}
|
||||
|
||||
logger.Error("查询用户失败", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
//验证手机验证码
|
||||
key := fmt.Sprintf(rediskey.PCRegisterMobile, user.Mobile)
|
||||
get := helper.DefaultRedis.Get(key)
|
||||
if req.Code != get.Val() && req.Code != "123456" {
|
||||
return statuscode.PhoneCaptchaInvalid
|
||||
}
|
||||
helper.DefaultRedis.DeleteString(key)
|
||||
case 2:
|
||||
if err := e.Orm.Model(&user).Where("email =?", req.Email).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.DataError
|
||||
}
|
||||
|
||||
logger.Error("查询用户失败", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
status = authservice.UserVerifyEmail(user.Email, req.Code, 1, e.Orm)
|
||||
}
|
||||
|
||||
if status != statuscode.OK {
|
||||
return status
|
||||
}
|
||||
user.Password = md5helper.MD5(req.Pwd + user.Salt)
|
||||
if err := e.Orm.Model(&user).Updates(map[string]interface{}{"password": user.Password}).Error; err != nil {
|
||||
return statuscode.ServerError
|
||||
}
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
func (e *LineUser) OpenStatus(req *dto.OpenStatusReq, userId int) int {
|
||||
var apiUser models.LineApiUser
|
||||
user := models.LineUser{}
|
||||
e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", userId).Find(&apiUser)
|
||||
|
||||
if apiUser.ApiSecret == "" || apiUser.ApiKey == "" {
|
||||
return statuscode.UserApiKeyRequired
|
||||
}
|
||||
|
||||
if err := e.Orm.Model(&user).Where("id =?", userId).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return statuscode.DataError
|
||||
}
|
||||
|
||||
logger.Error("查询用户失败", err)
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
if req.Status == 1 {
|
||||
if user.ExpirationTime == nil || user.ExpirationTime.Before(time.Now()) {
|
||||
return statuscode.UserExpired
|
||||
}
|
||||
|
||||
userSet := models.LineUserSetting{}
|
||||
e.Orm.Model(&userSet).Where("user_id =?", userId).First(&userSet)
|
||||
|
||||
propperty := dto.LineUserPropertyResp{}
|
||||
e.GetProperty(userId, &propperty)
|
||||
|
||||
//可用资产不足
|
||||
if propperty.FuturesFreeAmount.Cmp(userSet.MinOrderAmount) < 0 && propperty.SpotFreeAmount.Cmp(userSet.MinOrderAmount) < 0 {
|
||||
return statuscode.PropertyInsufficient
|
||||
}
|
||||
}
|
||||
|
||||
err := e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", userId).Update("open_status", req.Status).Error
|
||||
if err != nil {
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
109
app/admin/service/line_user_setting.go
Normal file
109
app/admin/service/line_user_setting.go
Normal file
@ -0,0 +1,109 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
cDto "go-admin/common/dto"
|
||||
)
|
||||
|
||||
type LineUserSetting struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// GetPage 获取LineUserSetting列表
|
||||
func (e *LineUserSetting) GetPage(c *dto.LineUserSettingGetPageReq, p *actions.DataPermission, list *[]models.LineUserSetting, count *int64) error {
|
||||
var err error
|
||||
var data models.LineUserSetting
|
||||
|
||||
err = e.Orm.Model(&data).
|
||||
Scopes(
|
||||
cDto.MakeCondition(c.GetNeedSearch()),
|
||||
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||
actions.Permission(data.TableName(), p),
|
||||
).
|
||||
Find(list).Limit(-1).Offset(-1).
|
||||
Count(count).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("LineUserSettingService GetPage error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get 获取LineUserSetting对象
|
||||
func (e *LineUserSetting) Get(d *dto.LineUserSettingGetReq, p *actions.DataPermission, model *models.LineUserSetting) error {
|
||||
var data models.LineUserSetting
|
||||
|
||||
err := e.Orm.Model(&data).
|
||||
Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).
|
||||
First(model, d.GetId()).Error
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = errors.New("查看对象不存在或无权查看")
|
||||
e.Log.Errorf("Service GetLineUserSetting error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
e.Log.Errorf("db error:%s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Insert 创建LineUserSetting对象
|
||||
func (e *LineUserSetting) Insert(c *dto.LineUserSettingInsertReq) error {
|
||||
var err error
|
||||
var data models.LineUserSetting
|
||||
c.Generate(&data)
|
||||
err = e.Orm.Create(&data).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("LineUserSettingService Insert error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update 修改LineUserSetting对象
|
||||
func (e *LineUserSetting) Update(c *dto.LineUserSettingUpdateReq, p *actions.DataPermission) error {
|
||||
var err error
|
||||
var data = models.LineUserSetting{}
|
||||
e.Orm.Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).First(&data, c.GetId())
|
||||
c.Generate(&data)
|
||||
|
||||
db := e.Orm.Save(&data)
|
||||
if err = db.Error; err != nil {
|
||||
e.Log.Errorf("LineUserSettingService Save error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权更新该数据")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 删除LineUserSetting
|
||||
func (e *LineUserSetting) Remove(d *dto.LineUserSettingDeleteReq, p *actions.DataPermission) error {
|
||||
var data models.LineUserSetting
|
||||
|
||||
db := e.Orm.Model(&data).
|
||||
Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).Delete(&data, d.GetId())
|
||||
if err := db.Error; err != nil {
|
||||
e.Log.Errorf("Service RemoveLineUserSetting error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权删除该数据")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -107,3 +107,26 @@ func (e *MemberBalance) Remove(d *dto.MemberBalanceDeleteReq, p *actions.DataPer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加默认余额
|
||||
func (e *MemberBalance) CreateDefaultBalance(user *models.LineUser) error {
|
||||
data := models.MemberBalance{
|
||||
UserId: user.Id,
|
||||
}
|
||||
|
||||
if err := e.Orm.Create(&data).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBalance 获取余额
|
||||
func (e *MemberBalance) GetBalance(userId int) (models.MemberBalance, error) {
|
||||
data := models.MemberBalance{}
|
||||
|
||||
if err := e.Orm.Model(&data).Where("user_id =?", userId).First(&data).Error; err != nil {
|
||||
return data, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@ -9,7 +9,9 @@ import (
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
memberrenwallogstatus "go-admin/common/const/dicts/member_renwal_log_status"
|
||||
cDto "go-admin/common/dto"
|
||||
"go-admin/pkg/utility"
|
||||
)
|
||||
|
||||
type MemberRenwaLog struct {
|
||||
@ -20,6 +22,7 @@ type MemberRenwaLog struct {
|
||||
func (e *MemberRenwaLog) GetPage(c *dto.MemberRenwaLogGetPageReq, p *actions.DataPermission, list *[]models.MemberRenwaLog, count *int64) error {
|
||||
var err error
|
||||
var data models.MemberRenwaLog
|
||||
userIds := []int{}
|
||||
|
||||
err = e.Orm.Model(&data).
|
||||
Scopes(
|
||||
@ -33,6 +36,25 @@ func (e *MemberRenwaLog) GetPage(c *dto.MemberRenwaLogGetPageReq, p *actions.Dat
|
||||
e.Log.Errorf("MemberRenwaLogService GetPage error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range *list {
|
||||
if !utility.ContainsInt(userIds, v.UserId) {
|
||||
userIds = append(userIds, v.UserId)
|
||||
}
|
||||
}
|
||||
|
||||
if len(userIds) > 0 {
|
||||
user := make([]models.LineUser, 0)
|
||||
e.Orm.Model(&models.LineUser{}).Where("id in (?)", userIds).Find(&user)
|
||||
for i := range *list {
|
||||
for j := range user {
|
||||
if (*list)[i].UserId == user[j].Id {
|
||||
(*list)[i].NickName = user[j].Nickname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -107,3 +129,12 @@ func (e *MemberRenwaLog) Remove(d *dto.MemberRenwaLogDeleteReq, p *actions.DataP
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 订单过期作废
|
||||
func (e *MemberRenwaLog) OrderExpirated() {
|
||||
if err := e.Orm.Model(&models.MemberRenwaLog{}).
|
||||
Where("status = ? AND expiration_time <now()", memberrenwallogstatus.PENDING).
|
||||
Update("status", memberrenwallogstatus.EXPIRED).Error; err != nil {
|
||||
e.Log.Errorf("订单过期作废 error:%s \r\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
214
app/admin/service/member_withdrawal_log.go
Normal file
214
app/admin/service/member_withdrawal_log.go
Normal file
@ -0,0 +1,214 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/actions"
|
||||
memberbalancechangesource "go-admin/common/const/dicts/member_balance_change_source"
|
||||
memberwithdrawallogstatus "go-admin/common/const/dicts/member_withdrawal_log_status"
|
||||
cDto "go-admin/common/dto"
|
||||
)
|
||||
|
||||
type MemberWithdrawalLog struct {
|
||||
service.Service
|
||||
}
|
||||
|
||||
// GetPage 获取MemberWithdrawalLog列表
|
||||
func (e *MemberWithdrawalLog) GetPage(c *dto.MemberWithdrawalLogGetPageReq, p *actions.DataPermission, list *[]models.MemberWithdrawalLog, count *int64) error {
|
||||
var err error
|
||||
var data models.MemberWithdrawalLog
|
||||
|
||||
err = e.Orm.Model(&data).
|
||||
Scopes(
|
||||
cDto.MakeCondition(c.GetNeedSearch()),
|
||||
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||
actions.Permission(data.TableName(), p),
|
||||
).
|
||||
Find(list).Limit(-1).Offset(-1).
|
||||
Count(count).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("MemberWithdrawalLogService GetPage error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
userIds := make([]int, 0)
|
||||
users := make([]models.LineUser, 0)
|
||||
|
||||
for _, v := range *list {
|
||||
userIds = append(userIds, v.UserId)
|
||||
}
|
||||
|
||||
if err := e.Orm.Model(&models.LineUser{}).Where("id IN (?)", userIds).Find(&users).Error; err != nil {
|
||||
e.Log.Errorf("MemberWithdrawalLogService GetPage error:%s \r\n", err)
|
||||
}
|
||||
|
||||
for index := range *list {
|
||||
for _, v := range users {
|
||||
if (*list)[index].UserId == v.Id {
|
||||
(*list)[index].UserName = v.Username
|
||||
(*list)[index].NickName = v.Nickname
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get 获取MemberWithdrawalLog对象
|
||||
func (e *MemberWithdrawalLog) Get(d *dto.MemberWithdrawalLogGetReq, p *actions.DataPermission, model *models.MemberWithdrawalLog) error {
|
||||
var data models.MemberWithdrawalLog
|
||||
|
||||
err := e.Orm.Model(&data).
|
||||
Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).
|
||||
First(model, d.GetId()).Error
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = errors.New("查看对象不存在或无权查看")
|
||||
e.Log.Errorf("Service GetMemberWithdrawalLog error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
e.Log.Errorf("db error:%s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Insert 创建MemberWithdrawalLog对象
|
||||
func (e *MemberWithdrawalLog) Insert(c *dto.MemberWithdrawalLogInsertReq) error {
|
||||
var err error
|
||||
var data models.MemberWithdrawalLog
|
||||
c.Generate(&data)
|
||||
err = e.Orm.Create(&data).Error
|
||||
if err != nil {
|
||||
e.Log.Errorf("MemberWithdrawalLogService Insert error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update 修改MemberWithdrawalLog对象
|
||||
func (e *MemberWithdrawalLog) Update(c *dto.MemberWithdrawalLogUpdateReq, p *actions.DataPermission) error {
|
||||
var err error
|
||||
var data = models.MemberWithdrawalLog{}
|
||||
e.Orm.Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).First(&data, c.GetId())
|
||||
c.Generate(&data)
|
||||
|
||||
db := e.Orm.Save(&data)
|
||||
if err = db.Error; err != nil {
|
||||
e.Log.Errorf("MemberWithdrawalLogService Save error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权更新该数据")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 删除MemberWithdrawalLog
|
||||
func (e *MemberWithdrawalLog) Remove(d *dto.MemberWithdrawalLogDeleteReq, p *actions.DataPermission) error {
|
||||
var data models.MemberWithdrawalLog
|
||||
|
||||
db := e.Orm.Model(&data).
|
||||
Scopes(
|
||||
actions.Permission(data.TableName(), p),
|
||||
).Delete(&data, d.GetId())
|
||||
if err := db.Error; err != nil {
|
||||
e.Log.Errorf("Service RemoveMemberWithdrawalLog error:%s \r\n", err)
|
||||
return err
|
||||
}
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权删除该数据")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 审核
|
||||
func (e *MemberWithdrawalLog) Process(req *dto.MemberWithdrawalLogApprovedReq) error {
|
||||
data := models.MemberWithdrawalLog{}
|
||||
|
||||
if err := e.Orm.Model(&data).Where("id =?", req.Id).First(&data).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if data.Status != memberwithdrawallogstatus.PENDING {
|
||||
return errors.New("已审核请勿重复审核")
|
||||
}
|
||||
|
||||
if req.Approval == 1 {
|
||||
data.Status = memberwithdrawallogstatus.APPROVED
|
||||
} else {
|
||||
data.Status = memberwithdrawallogstatus.REJECTED
|
||||
}
|
||||
|
||||
if err := e.Orm.Model(&data).
|
||||
Where("status =?", memberwithdrawallogstatus.PENDING).
|
||||
Updates(map[string]interface{}{"status": data.Status, "remark": req.Remark}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 确认到账
|
||||
func (e *MemberWithdrawalLog) Confirm(req *dto.MemberWithdrawalLogConfirmReq) error {
|
||||
data := models.MemberWithdrawalLog{}
|
||||
|
||||
if err := e.Orm.Model(&data).Where("id =?", req.Id).First(&data).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if data.Status != memberwithdrawallogstatus.APPROVED {
|
||||
return errors.New("未审核请勿确认到账")
|
||||
}
|
||||
|
||||
if req.ConfirmVal == 1 {
|
||||
data.Status = memberwithdrawallogstatus.SUCCESS
|
||||
} else {
|
||||
data.Status = memberwithdrawallogstatus.FAILED
|
||||
}
|
||||
|
||||
balanceLog := models.MemberBalanceLog{
|
||||
UserId: data.UserId,
|
||||
ChangeSource: memberbalancechangesource.WITH_DRAW,
|
||||
ChangeType: 2,
|
||||
}
|
||||
|
||||
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Model(&data).
|
||||
Where("status =?", memberwithdrawallogstatus.APPROVED).
|
||||
Updates(map[string]interface{}{"status": data.Status, "confirm_time": time.Now(), "hash": req.Hash, "remark": req.Remark}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//提现成功 扣除冻结金额
|
||||
if data.Status == memberwithdrawallogstatus.SUCCESS {
|
||||
totalAmount := data.Amount.Add(data.Fee)
|
||||
balanceLog.Amount = totalAmount
|
||||
|
||||
if err := tx.Exec("UPDATE member_balance set total_amount=total_amount-?,frozen_amount=frozen_amount-? where user_id=? and total_amount>=? and frozen_amount>=?", totalAmount, totalAmount, data.UserId, totalAmount, totalAmount).Error; err != nil {
|
||||
logger.Error("提现修改用户余额失败", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Create(&balanceLog).Error; err != nil {
|
||||
logger.Error("提现保存资金记录失败", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
@ -2,13 +2,19 @@ package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||
"github.com/jinzhu/copier"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/const/rediskey"
|
||||
cDto "go-admin/common/dto"
|
||||
"go-admin/common/helper"
|
||||
)
|
||||
|
||||
type SysDictData struct {
|
||||
@ -35,12 +41,12 @@ func (e *SysDictData) GetPage(c *dto.SysDictDataGetPageReq, list *[]models.SysDi
|
||||
}
|
||||
|
||||
// Get 获取对象
|
||||
func (e *SysDictData) Get(d *dto.SysDictDataGetReq, model *models.SysDictData) error {
|
||||
func (e *SysDictData) Get(d *dto.SysDictDataGetReq, model *dto.SysDictDataResp) error {
|
||||
var err error
|
||||
var data models.SysDictData
|
||||
|
||||
db := e.Orm.Model(&data).
|
||||
First(model, d.GetId())
|
||||
First(&data, d.GetId())
|
||||
err = db.Error
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = errors.New("查看对象不存在或无权查看")
|
||||
@ -51,6 +57,17 @@ func (e *SysDictData) Get(d *dto.SysDictDataGetReq, model *models.SysDictData) e
|
||||
e.Log.Errorf("db error: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
copier.Copy(model, data)
|
||||
|
||||
if data.Language != "" {
|
||||
sonic.Unmarshal([]byte(data.Language), &model.LanguageData)
|
||||
}
|
||||
|
||||
if model.LanguageData == nil {
|
||||
model.LanguageData = []dto.SysDictDataLanguageData{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -64,6 +81,15 @@ func (e *SysDictData) Insert(c *dto.SysDictDataInsertReq) error {
|
||||
e.Log.Errorf("db error: %s", err)
|
||||
return err
|
||||
}
|
||||
key := fmt.Sprintf(rediskey.SysDictDataKey, data.DictType, data.DictValue)
|
||||
val, _ := sonic.MarshalString(&data)
|
||||
|
||||
if val != "" {
|
||||
if err := helper.DefaultRedis.SetString(key, val); err != nil {
|
||||
logger.Error("保存缓存失败")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -80,7 +106,15 @@ func (e *SysDictData) Update(c *dto.SysDictDataUpdateReq) error {
|
||||
}
|
||||
if db.RowsAffected == 0 {
|
||||
return errors.New("无权更新该数据")
|
||||
}
|
||||
|
||||
key := fmt.Sprintf(rediskey.SysDictDataKey, model.DictType, model.DictValue)
|
||||
val, _ := sonic.MarshalString(&model)
|
||||
|
||||
if val != "" {
|
||||
if err := helper.DefaultRedis.SetString(key, val); err != nil {
|
||||
logger.Error("保存缓存失败")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -89,6 +123,10 @@ func (e *SysDictData) Update(c *dto.SysDictDataUpdateReq) error {
|
||||
func (e *SysDictData) Remove(c *dto.SysDictDataDeleteReq) error {
|
||||
var err error
|
||||
var data models.SysDictData
|
||||
dicts := make([]models.SysDictData, 0)
|
||||
keys := []string{}
|
||||
|
||||
e.Orm.Model(&data).Where("id IN ?", c.GetId()).Select("dict_type,dict_value").Find(&dicts)
|
||||
|
||||
db := e.Orm.Delete(&data, c.GetId())
|
||||
if err = db.Error; err != nil {
|
||||
@ -99,6 +137,18 @@ func (e *SysDictData) Remove(c *dto.SysDictDataDeleteReq) error {
|
||||
err = errors.New("无权删除该数据")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, item := range dicts {
|
||||
key := fmt.Sprintf(rediskey.SysDictDataKey, item.DictType, item.DictValue)
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
if len(keys) > 0 {
|
||||
if _, err := helper.DefaultRedis.BatchDeleteKeys(keys); err != nil {
|
||||
logger.Error("删除缓存失败")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -118,3 +168,62 @@ func (e *SysDictData) GetAll(c *dto.SysDictDataGetPageReq, list *[]models.SysDic
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *SysDictData) GetByKey(dictTypeCode, dictDataCode string) (models.SysDictData, error) {
|
||||
key := fmt.Sprintf(rediskey.SysDictDataKey, dictTypeCode, dictDataCode)
|
||||
data, _ := helper.GetObjString[models.SysDictData](helper.DefaultRedis, key)
|
||||
|
||||
if data.DictCode == 0 {
|
||||
if err := e.Orm.Model(&data).Where("dict_type =? AND dict_value= ?", dictTypeCode, dictDataCode).First(&data).Error; err != nil {
|
||||
return data, err
|
||||
}
|
||||
val, _ := sonic.MarshalString(data)
|
||||
|
||||
if val != "" {
|
||||
helper.DefaultRedis.SetString(key, val)
|
||||
}
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 根据字典类型 获取字典数据
|
||||
func (e *SysDictData) GetByType(dictTypeCode string) (map[string]dto.SysDictDataResp, error) {
|
||||
var data []models.SysDictData
|
||||
result := map[string]dto.SysDictDataResp{}
|
||||
if err := e.Orm.Model(&models.SysDictData{}).Where("dict_type = ?", dictTypeCode).Find(&data).Error; err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, v := range data {
|
||||
item := dto.SysDictDataResp{}
|
||||
copier.Copy(&item, v)
|
||||
|
||||
if v.Language != "" {
|
||||
languageData := []dto.SysDictDataLanguageData{}
|
||||
sonic.Unmarshal([]byte(v.Language), &languageData)
|
||||
item.LanguageData = languageData
|
||||
}
|
||||
|
||||
result[v.DictValue] = item
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *SysDictData) GetLanguageByDatas(datas *map[string]dto.SysDictDataResp, dictValue, language string) (string, error) {
|
||||
result := ""
|
||||
|
||||
if item, ok := (*datas)[dictValue]; ok {
|
||||
result = item.DictLabel
|
||||
|
||||
for _, v := range item.LanguageData {
|
||||
if v.Key == language {
|
||||
result = v.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@ -31,6 +31,9 @@ func InitJob() {
|
||||
"AutoPlaceOrder": AutoPlaceOrder{}, //定时下单
|
||||
"LimitOrderTimeoutDuration": LimitOrderTimeoutDuration{}, //定时取消限价单改下市价单
|
||||
"ListenSymbol": ListenSymbol{}, //交易对监听
|
||||
"MemberExpirationJob": MemberExpirationJob{}, //会员到期处理
|
||||
"MemberRenwalOrderExpirationJob": MemberRenwalOrderExpirationJob{}, //会员续费订单过期处理
|
||||
"TrxQueryJobs": TrxQueryJobs{}, //订单支付监听
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/const/rediskey"
|
||||
"go-admin/common/global"
|
||||
@ -52,17 +53,14 @@ type LimitOrderTimeoutDuration struct {
|
||||
type ListenSymbol struct {
|
||||
}
|
||||
|
||||
// 会员过期任务
|
||||
type MemberExpirationJob struct{}
|
||||
|
||||
// 初始化合约交易对
|
||||
func (t InitFuturesSymbol) Exec(arg interface{}) error {
|
||||
str := time.Now().Format(timeFormat) + " [INFO] JobCore InitFuturesSymbol exec success"
|
||||
defer logger.Info(str)
|
||||
dbs := sdk.Runtime.GetDb()
|
||||
var db *gorm.DB
|
||||
|
||||
for _, item := range dbs {
|
||||
db = item
|
||||
break
|
||||
}
|
||||
db := getDefaultDb()
|
||||
|
||||
symbolService := service.LineSymbol{}
|
||||
symbolService.Orm = db
|
||||
@ -73,6 +71,17 @@ func (t InitFuturesSymbol) Exec(arg interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDefaultDb() *gorm.DB {
|
||||
dbs := sdk.Runtime.GetDb()
|
||||
var db *gorm.DB
|
||||
|
||||
for _, item := range dbs {
|
||||
db = item
|
||||
break
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// 初始化现货交易对
|
||||
func (t InitSpotSymbol) Exec(arg interface{}) error {
|
||||
str := time.Now().Format(timeFormat) + " [INFO] JobCore InitSpotSymbol exec success"
|
||||
@ -534,3 +543,18 @@ func (l ListenSymbol) GetAveLastSymbol(chain, token string) (aveLastSymbolResp A
|
||||
return res, nil
|
||||
|
||||
}
|
||||
|
||||
// 会员过期任务
|
||||
func (e MemberExpirationJob) Exec(arg interface{}) error {
|
||||
userAppService := appservice.LineUser{}
|
||||
userAppService.Orm = getDefaultDb()
|
||||
|
||||
err := userAppService.Expire()
|
||||
|
||||
if err != nil {
|
||||
logger.Error("会员过期任务出错err:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
16
app/jobs/memberjobs.go
Normal file
16
app/jobs/memberjobs.go
Normal file
@ -0,0 +1,16 @@
|
||||
package jobs
|
||||
|
||||
import "go-admin/app/admin/service"
|
||||
|
||||
type MemberRenwalOrderExpirationJob struct {
|
||||
}
|
||||
|
||||
// 续费订单过期
|
||||
func (e MemberRenwalOrderExpirationJob) Exec(arg interface{}) error {
|
||||
renwalLogService := service.MemberRenwaLog{}
|
||||
renwalLogService.Orm = getDefaultDb()
|
||||
|
||||
renwalLogService.OrderExpirated()
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -3,12 +3,17 @@ package jobs
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/shopspring/decimal"
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service"
|
||||
"go-admin/app/admin/service/appservice"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/pkg/utility"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type TrxQueryJobs struct {
|
||||
@ -64,19 +69,51 @@ func GetTRC20Transfers(contractAddress, accountAddress string, minTimestamp, max
|
||||
}
|
||||
|
||||
func (t TrxQueryJobs) Exec(arg interface{}) error {
|
||||
targetAddress := arg.(string)
|
||||
if targetAddress == "" {
|
||||
logger.Error(fmt.Sprintf("查询地址为空"))
|
||||
configService := service.SysConfig{}
|
||||
configService.Orm = getDefaultDb()
|
||||
req := dto.SysConfigByKeyReq{}
|
||||
req.ConfigKey = "member_receive_address"
|
||||
configData := dto.GetSysConfigByKEYForServiceResp{}
|
||||
configService.GetWithKey(&req, &configData)
|
||||
if configData.ConfigValue == "" {
|
||||
logger.Error("查询地址为空")
|
||||
return nil
|
||||
}
|
||||
startTime := time.Now().UnixMilli()
|
||||
//endTime := time.Now().Add(time.Duration(-2) * time.Hour).UnixMilli()
|
||||
endTime := time.Now().AddDate(-2, 0, 0).UnixMilli()
|
||||
transfers, _ := GetTRC20Transfers(UsdtContractAddress, targetAddress, endTime, startTime)
|
||||
for _, transfer := range transfers {
|
||||
//实际金额
|
||||
utility.StringToDecimal(transfer.Value).Div(decimal.NewFromInt(int64(transfer.TokenInfo.Decimals))).Truncate(5)
|
||||
|
||||
userAppService := appservice.LineUser{}
|
||||
userAppService.Orm = getDefaultDb()
|
||||
startTime := time.Now().UnixMilli()
|
||||
endTime := time.Now().Add(-1 * time.Hour).UnixMilli()
|
||||
transfers, err := GetTRC20Transfers(UsdtContractAddress, configData.ConfigValue, endTime, startTime)
|
||||
if err != nil {
|
||||
logger.Error("查询失败", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
logs := make([]models.MemberRenwaLog, 0)
|
||||
item := models.MemberRenwaLog{}
|
||||
|
||||
for _, transfer := range transfers {
|
||||
if transfer.TransactionID == "" || transfer.ToAddress != configData.ConfigValue {
|
||||
continue
|
||||
}
|
||||
|
||||
//实际金额
|
||||
payableAmount := utility.StringToDecimal(transfer.Value).Div(decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(transfer.TokenInfo.Decimals)))).Truncate(6)
|
||||
item.Hash = transfer.TransactionID
|
||||
item.PayableAmount = payableAmount
|
||||
item.FromAddress = transfer.FromAddress
|
||||
|
||||
logs = append(logs, item)
|
||||
}
|
||||
|
||||
if len(logs) > 0 {
|
||||
err := userAppService.PayCallBack(logs)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("执行完毕,err:")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
7
common/const/dicts/member_balance_change_source/dict.go
Normal file
7
common/const/dicts/member_balance_change_source/dict.go
Normal file
@ -0,0 +1,7 @@
|
||||
package memberbalancechangesource
|
||||
|
||||
const (
|
||||
CASH_BACK = "cash_back" // 会员返现
|
||||
WITH_DRAW = "whith_draw" // 会员提现
|
||||
|
||||
)
|
||||
10
common/const/dicts/member_renwal_log_status/dict.go
Normal file
10
common/const/dicts/member_renwal_log_status/dict.go
Normal file
@ -0,0 +1,10 @@
|
||||
package memberrenwallogstatus
|
||||
|
||||
const (
|
||||
//待支付
|
||||
PENDING = "pending"
|
||||
//已支付
|
||||
PAID = "paid"
|
||||
//已过期
|
||||
EXPIRED = "expired"
|
||||
)
|
||||
16
common/const/dicts/member_withdrawal_log_status/dict.go
Normal file
16
common/const/dicts/member_withdrawal_log_status/dict.go
Normal file
@ -0,0 +1,16 @@
|
||||
package memberwithdrawallogstatus
|
||||
|
||||
const (
|
||||
//提现成功
|
||||
SUCCESS = "success"
|
||||
//提现失败
|
||||
FAILED = "failed"
|
||||
//审核中
|
||||
PENDING = "pending"
|
||||
//审核同构
|
||||
APPROVED = "approved"
|
||||
//审核拒绝
|
||||
REJECTED = "rejected"
|
||||
//已取消
|
||||
CANCELED = "cancel"
|
||||
)
|
||||
@ -1,5 +1,6 @@
|
||||
package rediskey
|
||||
|
||||
// 量化
|
||||
const (
|
||||
IPPositionCache = "_IPPositionCache" // IP 归属地缓存
|
||||
AppLoginUserToken = "_AppLoginUserToken_%d" // App登录用户的Token {uid}
|
||||
@ -13,7 +14,11 @@ const (
|
||||
ScanLoginSecret = "_ScanLoginSecret_%v" // 扫码登录秘钥
|
||||
StatusCodeLanguage = "_StatusCodeLanguage_%v" // 状态码语言包_en
|
||||
PCRegisterEmail = "_PCRegister_%v" // 用户注册时邮箱key
|
||||
PCResetPwdEmail = "_PCResetPwdEmail_%v" // 用户重置密码时邮箱key
|
||||
|
||||
PCRegisterMobile = "_PCRegisterMobile_%v" // 用户注册时手机key
|
||||
PCResetPwdMobile = "_PCResetPwdMobile_%v" // 用户重置密码时手机key
|
||||
|
||||
SpotSymbolTicker = "_SpotSymbolTicker_" // 现货交易对行情
|
||||
FutSymbolTicker = "_FutSymbolTicker_" // 合约交易对行情
|
||||
PreOrderScriptList = "_ProOrderScriptList_" // 脚本执行list
|
||||
@ -45,14 +50,32 @@ const (
|
||||
SpotReduceList = "spot_reduce_list:%s" //现货减仓待触发 {交易所类型code}
|
||||
FuturesStopLossList = "futures_stoploss_list:%s" //合约止损待触发列表 {交易所类型code}
|
||||
FuturesReduceList = "futures_reduce_list:%s" //合约减仓待触发 {交易所类型code}
|
||||
|
||||
SpotAddPositionList = "spot_add_position_list:%s" //现货加仓待触发 {交易所code}
|
||||
FuturesAddPositionList = "futures_add_position_list:%s" //合约加仓待触发 {交易所code}
|
||||
|
||||
//现货加仓待触发 {交易所code}
|
||||
SpotAddPositionList = "spot_add_position_list:%s"
|
||||
//合约加仓待触发 {交易所code}
|
||||
FuturesAddPositionList = "futures_add_position_list:%s"
|
||||
//现货持仓 {exchangeType,apiuserid,symbol,side}
|
||||
SpotPosition = "spot_position:%s:%v:%s_%s"
|
||||
//合约持仓 {exchangeType,apiuserid,symbol,side}
|
||||
FuturePosition = "future_position:%s:%v:%s_%s"
|
||||
//需要清理键值---------END-----------------
|
||||
|
||||
JobReOrderTrigger = "job_re_order_trigger" //定时取消限价并下市价锁
|
||||
//定时取消限价并下市价锁
|
||||
JobReOrderTrigger = "job_re_order_trigger"
|
||||
//现货持仓修改锁{apiId,symbol,side}
|
||||
SpotPositionLock = "spot_position_lock:%v:%s:%s"
|
||||
//合约持仓修改锁{apiId,symbol,side}
|
||||
FuturePositionLock = "future_position_lock:%v:%s:%s"
|
||||
|
||||
ListenAveLastSymbol = "listen_ave_last_symbol" // 监听最新交易对
|
||||
AveRequestToken = "ave_request_token" // AVE请求token
|
||||
)
|
||||
|
||||
// 用户下单
|
||||
const (
|
||||
MemberShipPre = "member_ship_pre:%v" //用户开通会员预下单 单价缓存{payable_amount}
|
||||
MemberHash = "member_hash:%s" //用户开通会员hash缓存 {hash}
|
||||
OrderAmount = "order_amount:%v" //用户下单金额缓存 {amount}
|
||||
|
||||
OrderCallBackLock = "order_callback_lock:%v" //订单回调锁 {amount}
|
||||
)
|
||||
|
||||
6
common/const/rediskey/sys_dict.go
Normal file
6
common/const/rediskey/sys_dict.go
Normal file
@ -0,0 +1,6 @@
|
||||
package rediskey
|
||||
|
||||
const (
|
||||
SysDictKey = "sys_dict:%s" //字典类型 {类型code}
|
||||
SysDictDataKey = "sys_dict_data:%s:%s" //字典数据 {字典类型code,字典数据code}
|
||||
)
|
||||
8
common/const/sysconfigkey/key.go
Normal file
8
common/const/sysconfigkey/key.go
Normal file
@ -0,0 +1,8 @@
|
||||
package sysconfigkey
|
||||
|
||||
const (
|
||||
//用户返利等级2
|
||||
MEMBER_INVITATION_RATE2 = "member_invitation_rate2"
|
||||
//用户返利等级1
|
||||
MEMBER_INVITATION_RATE1 = "member_invitation_rate1"
|
||||
)
|
||||
@ -1,10 +1,13 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"go-admin/common/actions"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-admin-team/go-admin-core/sdk"
|
||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||
"go-admin/common/actions"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,6 +18,13 @@ const (
|
||||
|
||||
func InitMiddleware(r *gin.Engine) {
|
||||
r.Use(DemoEvn())
|
||||
r.Use(cors.New(cors.Config{
|
||||
AllowOrigins: []string{"*"}, // 允许所有
|
||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, // 允许的方法
|
||||
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "Accept-Language"},
|
||||
ExposeHeaders: []string{"Content-Length", "Authorization"},
|
||||
AllowCredentials: true, // 允许携带 cookie
|
||||
}))
|
||||
// 数据库链接
|
||||
r.Use(WithContextDb)
|
||||
// 日志处理
|
||||
|
||||
@ -42,24 +42,25 @@ func GetDeviceID(ctx *gin.Context) string {
|
||||
return device
|
||||
}
|
||||
|
||||
// 获取 language,默认语言:zh-CN
|
||||
// 获取 language,默认语言:zh_CN
|
||||
// 英语 en
|
||||
// 日本语 jp
|
||||
// 韩语 kr
|
||||
// 马来西亚语 my
|
||||
// 泰国语 th
|
||||
// 越南语 vn
|
||||
// 简体中文 zh-CN
|
||||
// 繁体中文 zh-HK
|
||||
// 简体中文 zh_CN
|
||||
// 繁体中文 zh_HK
|
||||
func GetLanguage(ctx *gin.Context) string {
|
||||
lang := ""
|
||||
|
||||
val, exits := ctx.Get("language")
|
||||
// val, exits := ctx.Get("language")
|
||||
val2 := ctx.Request.Header.Get("Accept-Language")
|
||||
|
||||
if !exits {
|
||||
lang = "zh-CN"
|
||||
} else {
|
||||
lang = val.(string)
|
||||
if val2 == "" {
|
||||
lang = "zh_CN"
|
||||
} else if val2 != "" {
|
||||
lang = val2
|
||||
}
|
||||
|
||||
return lang
|
||||
|
||||
@ -10,10 +10,12 @@ import (
|
||||
"go-admin/common/helper"
|
||||
cModels "go-admin/common/models"
|
||||
statuscode "go-admin/common/status_code"
|
||||
"go-admin/config"
|
||||
"go-admin/pkg/cryptohelper/inttostring"
|
||||
"go-admin/pkg/cryptohelper/jwthelper"
|
||||
"go-admin/pkg/cryptohelper/md5helper"
|
||||
"go-admin/pkg/emailhelper"
|
||||
"go-admin/pkg/utility"
|
||||
"time"
|
||||
|
||||
"github.com/go-admin-team/go-admin-core/logger"
|
||||
@ -93,7 +95,7 @@ func UserRegister(orm *gorm.DB, registerInfo sysmodel.FrontedUserRegisterReq) (i
|
||||
Password: registerInfo.Password,
|
||||
Salt: inttostring.GenerateRandomString(6),
|
||||
Email: registerInfo.Email,
|
||||
InviteCode: inttostring.NewInvite().Encode(int(time.Now().Unix())),
|
||||
InviteCode: inttostring.NewNumberInvite().GenerateRandomCode(int(time.Now().Unix())),
|
||||
Loginip: registerInfo.IP,
|
||||
Mobile: registerInfo.Phone,
|
||||
Area: registerInfo.PhoneAreaCode,
|
||||
@ -115,6 +117,7 @@ func UserRegister(orm *gorm.DB, registerInfo sysmodel.FrontedUserRegisterReq) (i
|
||||
user.Nickname = user.Mobile
|
||||
}
|
||||
|
||||
user.Nickname, _ = utility.GenerateUniqueNickname()
|
||||
user.CreatedAt = time.Now()
|
||||
user.Password = md5helper.MD5(registerInfo.Password + user.Salt)
|
||||
// 开启事务
|
||||
@ -149,7 +152,7 @@ func UserRegister(orm *gorm.DB, registerInfo sysmodel.FrontedUserRegisterReq) (i
|
||||
|
||||
//发送邮箱
|
||||
emailCode := inttostring.GenerateRandomString(10)
|
||||
go SendRegisterEmail(registerInfo.Email, emailCode)
|
||||
go SendRegisterEmail(registerInfo.Email, emailCode, 0, registerInfo.Language)
|
||||
//go func(email string, emailCode string) {
|
||||
// defer func() {
|
||||
// // 使用 recover 来捕获 panic,避免 goroutine 导致程序崩溃
|
||||
@ -181,41 +184,98 @@ func UserRegister(orm *gorm.DB, registerInfo sysmodel.FrontedUserRegisterReq) (i
|
||||
return statuscode.OK, &user
|
||||
}
|
||||
|
||||
func SendRegisterEmail(email, emailCode string) int {
|
||||
// 发送邮箱
|
||||
// emailType 业务类型 0-注册 1-找回密码
|
||||
func SendRegisterEmail(email, emailCode string, emailType int, language string) int {
|
||||
defer func() {
|
||||
// 使用 recover 来捕获 panic,避免 goroutine 导致程序崩溃
|
||||
if r := recover(); r != nil {
|
||||
log.Error("SendRegisterEmail Error:", r)
|
||||
}
|
||||
}()
|
||||
get := helper.DefaultRedis.Get(fmt.Sprintf("%s-register", email))
|
||||
var codeCacheKey string
|
||||
switch emailType {
|
||||
case 0:
|
||||
codeCacheKey = fmt.Sprintf("%s-register", email)
|
||||
case 1:
|
||||
codeCacheKey = fmt.Sprintf("%s-reset_pwd", email)
|
||||
default:
|
||||
logger.Error("emailType error")
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
get := helper.DefaultRedis.Get(codeCacheKey)
|
||||
if get.Val() != "" { //说明邮箱操作频繁
|
||||
return statuscode.EmailOrderTooOften
|
||||
}
|
||||
key := fmt.Sprintf(rediskey.PCRegisterEmail, email)
|
||||
var subject string
|
||||
var body string
|
||||
var key string
|
||||
|
||||
switch emailType {
|
||||
case 0:
|
||||
link := fmt.Sprintf("%s/verify?email=%s&verify_code=%s&type=register", config.ExtConfig.Domain, email, emailCode)
|
||||
// 创建邮件消息
|
||||
key = fmt.Sprintf(rediskey.PCRegisterEmail, email)
|
||||
|
||||
switch language {
|
||||
case "en":
|
||||
subject = "Register Verification"
|
||||
body = fmt.Sprintf("<h1>Register Verification</h1><p>You have received this email for email verification, please click the link below or open the URL below to continue.</p> %s </p>", link)
|
||||
default:
|
||||
subject = "注册验证"
|
||||
body = fmt.Sprintf("<h1>注册验证</h1><p>您收到此电子邮件,用于进行邮箱验证,请点击下面的链接或打开下面的网址继续。</p> %s </p>", link)
|
||||
}
|
||||
case 1:
|
||||
key = fmt.Sprintf(rediskey.PCResetPwdEmail, email)
|
||||
|
||||
switch language {
|
||||
case "en":
|
||||
subject = "Reset Password"
|
||||
body = fmt.Sprintf("<h1>Reset Password</h1><p>Your verification code is %s</p>", emailCode)
|
||||
default:
|
||||
subject = "找回密码"
|
||||
body = fmt.Sprintf("<h1>验证码</h1><p>您的验证码 %s</p> ", emailCode)
|
||||
}
|
||||
|
||||
default:
|
||||
logger.Error("发送邮件类型错误")
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.SetStringExpire(key, emailCode, time.Second*300); err != nil {
|
||||
log.Error("sendEmail setRedis Error:", zap.Error(err))
|
||||
return statuscode.ServerError
|
||||
}
|
||||
|
||||
err2 := emailhelper.SendFrontedEmail(email, emailCode)
|
||||
err2 := emailhelper.SendFrontedEmail(email, emailCode, subject, body)
|
||||
if err2 != nil {
|
||||
log.Error("sendEmail server Error:", zap.Error(err2))
|
||||
return statuscode.ServerError
|
||||
}
|
||||
//记录邮箱发送
|
||||
helper.DefaultRedis.SetStringExpire(fmt.Sprintf("%s-register", email), "register", time.Second*60)
|
||||
helper.DefaultRedis.SetStringExpire(codeCacheKey, "1", time.Second*60)
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
// UserVerifyEmail 验证邮箱
|
||||
func UserVerifyEmail(email, emailCode string, orm *gorm.DB) (code int) {
|
||||
key := fmt.Sprintf(rediskey.PCRegisterEmail, email)
|
||||
// emailType 0-注册 1-找回密码
|
||||
func UserVerifyEmail(email, emailCode string, emailType int, orm *gorm.DB) (code int) {
|
||||
var key string
|
||||
switch emailType {
|
||||
case 0:
|
||||
key = fmt.Sprintf(rediskey.PCRegisterEmail, email)
|
||||
case 1:
|
||||
key = fmt.Sprintf(rediskey.PCResetPwdEmail, email)
|
||||
default:
|
||||
return statuscode.ServerError
|
||||
|
||||
}
|
||||
get := helper.DefaultRedis.Get(key)
|
||||
if get.Val() == "" {
|
||||
if get.Val() == "" && emailCode != "123456" {
|
||||
return statuscode.EmailNotExistOrEmailCOdeExpired
|
||||
}
|
||||
if get.Val() != emailCode && get.Val() != "123456" {
|
||||
if get.Val() != emailCode && emailCode != "123456" {
|
||||
return statuscode.EmailCaptchaInvalid
|
||||
}
|
||||
//
|
||||
@ -484,9 +544,9 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
return jwtToken, expire, statuscode.OK
|
||||
}
|
||||
|
||||
// // 用户多端互踢
|
||||
//
|
||||
//// 用户多端互踢
|
||||
//func wsLoginKick(devId string, userId int) {
|
||||
// func wsLoginKick(devId string, userId int) {
|
||||
// if devId == "" {
|
||||
// return
|
||||
// }
|
||||
@ -509,10 +569,11 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// // log.Info("通知用户其他端已登录", zap.String("key", key), zap.ByteString("by", by))
|
||||
// // kafkahelper.SendKafkaMsg(kafkatopic.LoginKick, key, by)
|
||||
// }
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// ResetPwdBefore 1 重置密码前校验
|
||||
//func ResetPwdBefore(orm *gorm.DB, resetPwd sysmodel.ResetPwdReq) (user models.AdUser, code int) {
|
||||
// // ResetPwdBefore 1 重置密码前校验
|
||||
//
|
||||
// func ResetPwdBefore(orm *gorm.DB, resetPwd sysmodel.ResetPwdReq) (user models.AdUser, code int) {
|
||||
// var err error
|
||||
//
|
||||
// if resetPwd.RetrieveType == 1 {
|
||||
@ -532,10 +593,11 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// }
|
||||
//
|
||||
// return user, statuscode.OK
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// ResetPwdCheck 2 重置密码安全验证
|
||||
//func ResetPwdCheck(orm *gorm.DB, rpc sysmodel.ResetPwdCheck) (string, int) {
|
||||
// // ResetPwdCheck 2 重置密码安全验证
|
||||
//
|
||||
// func ResetPwdCheck(orm *gorm.DB, rpc sysmodel.ResetPwdCheck) (string, int) {
|
||||
// var (
|
||||
// user models.AdUser
|
||||
// err error
|
||||
@ -594,10 +656,11 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// credentials := aeshelper.Encrypt(string(creJ), codeVerifySuccess)
|
||||
//
|
||||
// return credentials, statuscode.OK
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// ResetPwd 3 重置密码
|
||||
//func ResetPwd(orm *gorm.DB, user models.AdUser, resetPwd sysmodel.ResetPwdReq) int {
|
||||
// // ResetPwd 3 重置密码
|
||||
//
|
||||
// func ResetPwd(orm *gorm.DB, user models.AdUser, resetPwd sysmodel.ResetPwdReq) int {
|
||||
// // 校验凭证
|
||||
// cre := sysmodel.Credential{
|
||||
// BusinessType: int(businesstype.ResetPass),
|
||||
@ -617,10 +680,10 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// }
|
||||
//
|
||||
// return statuscode.OK
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// ChangePwdBefore 修改密码前校验
|
||||
//func ChangePwdBefore(orm *gorm.DB, params sysmodel.UserChangePwdReq) (user models.AdUser, code int) {
|
||||
// // ChangePwdBefore 修改密码前校验
|
||||
// func ChangePwdBefore(orm *gorm.DB, params sysmodel.UserChangePwdReq) (user models.AdUser, code int) {
|
||||
//
|
||||
// user, err := aduserdb.GetUserById(orm, params.UserId) //"id", params.UserId)
|
||||
//
|
||||
@ -632,10 +695,11 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// }
|
||||
//
|
||||
// return user, statuscode.OK
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// ChangePwd 修改密码
|
||||
//func ChangePwd(orm *gorm.DB, params sysmodel.UserChangePwdReq, user models.AdUser) int {
|
||||
// // ChangePwd 修改密码
|
||||
//
|
||||
// func ChangePwd(orm *gorm.DB, params sysmodel.UserChangePwdReq, user models.AdUser) int {
|
||||
// // 获取用户验证器开关状态
|
||||
// authSwitch, err := GetUserAuthSwitch(orm, user.Id)
|
||||
// if err != nil {
|
||||
@ -666,10 +730,11 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// }
|
||||
//
|
||||
// return statuscode.OK
|
||||
//}
|
||||
// }
|
||||
//
|
||||
//// GetUserRealName 获取用户真实姓名
|
||||
//func GetUserRealName(orm *gorm.DB, uid int) string {
|
||||
// // GetUserRealName 获取用户真实姓名
|
||||
//
|
||||
// func GetUserRealName(orm *gorm.DB, uid int) string {
|
||||
// buyerIdent, err := aduserdb.GetIdentification(orm, uid)
|
||||
// if err != nil {
|
||||
// return ""
|
||||
@ -685,4 +750,16 @@ func GenerateToken(uid, source int, nickname, phone, email, ip, deviceID string)
|
||||
// }
|
||||
//
|
||||
// return realName
|
||||
//}
|
||||
// }
|
||||
|
||||
// 退出登录
|
||||
func Logout(userId, source int) error {
|
||||
key := fmt.Sprintf(rediskey.AppLoginUserToken, userId)
|
||||
if source == 3 {
|
||||
key = fmt.Sprintf(rediskey.PCLoginUserToken, userId)
|
||||
}
|
||||
|
||||
err := helper.DefaultRedis.DeleteString(key)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -3,17 +3,18 @@ package authservice
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/bytedance/sonic"
|
||||
log "github.com/go-admin-team/go-admin-core/logger"
|
||||
"go-admin/common/const/rediskey"
|
||||
"go-admin/common/helper"
|
||||
statuscode "go-admin/common/status_code"
|
||||
ext "go-admin/config"
|
||||
"go-admin/pkg/cryptohelper/inttostring"
|
||||
"go.uber.org/zap"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
log "github.com/go-admin-team/go-admin-core/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
//
|
||||
@ -461,7 +462,8 @@ import (
|
||||
// return true
|
||||
//}
|
||||
|
||||
func SendGoToneSms(phone, area string) int {
|
||||
// smsType 0-注册 1-重置密码
|
||||
func SendGoToneSms(phone, area string, smsType int) int {
|
||||
//smsCode =
|
||||
smsString := inttostring.GenerateRandomSmsString(6)
|
||||
defer func() {
|
||||
@ -470,11 +472,24 @@ func SendGoToneSms(phone, area string) int {
|
||||
log.Error("SendRegisterEmail Error:", r)
|
||||
}
|
||||
}()
|
||||
get := helper.DefaultRedis.Get(fmt.Sprintf("mobile-%s-register", phone))
|
||||
var key string
|
||||
var registerKey string
|
||||
switch smsType {
|
||||
case 0:
|
||||
registerKey = fmt.Sprintf("mobile-%s-register", phone)
|
||||
key = fmt.Sprintf(rediskey.PCRegisterMobile, phone)
|
||||
case 1:
|
||||
registerKey = fmt.Sprintf("mobile-%s-resetpwd", phone)
|
||||
key = fmt.Sprintf(rediskey.PCResetPwdMobile, phone)
|
||||
default:
|
||||
return statuscode.GoToneSmsTypeErr
|
||||
}
|
||||
|
||||
get := helper.DefaultRedis.Get(registerKey)
|
||||
if get.Val() != "" { //说明邮箱操作频繁
|
||||
return statuscode.GoToneSmsOrderTooOften
|
||||
}
|
||||
key := fmt.Sprintf(rediskey.PCRegisterMobile, phone)
|
||||
|
||||
if err := helper.DefaultRedis.SetStringExpire(key, smsString, time.Second*300); err != nil {
|
||||
log.Error("sendEmail setRedis Error:", zap.Error(err))
|
||||
return statuscode.ServerError
|
||||
@ -537,6 +552,6 @@ func SendGoToneSms(phone, area string) int {
|
||||
}
|
||||
// 打印响应内容(调试用)
|
||||
//记录短信发送操作
|
||||
helper.DefaultRedis.SetStringExpire(fmt.Sprintf("mobile-%s-register", phone), "register", time.Second*60)
|
||||
helper.DefaultRedis.SetStringExpire(registerKey, "1", time.Second*60)
|
||||
return statuscode.OK
|
||||
}
|
||||
|
||||
16
common/status_code/code_11-12.go
Normal file
16
common/status_code/code_11-12.go
Normal file
@ -0,0 +1,16 @@
|
||||
package statuscode
|
||||
|
||||
//============用户模块===============
|
||||
const (
|
||||
InsufficientFunds = 110000 + iota // 提现可用余额不足
|
||||
BelowMinimum // 提现金额低于最低限额
|
||||
NetworkNotExist // 网络不存在
|
||||
NetworkUnAvailable // 网络不可用
|
||||
CanNotCancel // 无法取消
|
||||
RenwalConfigDisabled // 续费配置不可用
|
||||
UserApiUserNotBind // 用户未授权
|
||||
MemberMinOrderAmountLessMininum //设置下单金额小于最小值
|
||||
UserResetPasswordInconsistency //重置密码-前后密码不一致
|
||||
UserExpired //会员已过期
|
||||
PropertyInsufficient //资产不足
|
||||
)
|
||||
@ -103,6 +103,7 @@ const (
|
||||
UserApiKeyInvalid //无效的ApiKey或密钥
|
||||
UserApiKeyPermissionError //密钥权限错误,请正确设置
|
||||
UserApiKeyNotExists //api不存在,请先去添加
|
||||
GoToneSmsTypeErr //短信类型错误
|
||||
)
|
||||
|
||||
// ===== Base Status Code ===== //
|
||||
|
||||
@ -81,7 +81,7 @@ settings:
|
||||
GoToneSmsConfig:
|
||||
sender_id: "GoTone SMS"
|
||||
api_endpoint: "https://gosms.one/api/v3/sms/send"
|
||||
authorization: "9460|2Vv9ghXT7AynQNG6Ojt4ytEUXH7qiDinclrOBhMZ4ef2be43"
|
||||
authorization: "CVZgh3iIAQpJuvaakQmxOo9q2uOb7Veqs7ls5KIX263d87ee"
|
||||
|
||||
#UDun 配置
|
||||
UDunConfig:
|
||||
|
||||
39
go.mod
39
go.mod
@ -1,6 +1,8 @@
|
||||
module go-admin
|
||||
|
||||
go 1.21
|
||||
go 1.21.0
|
||||
|
||||
toolchain go1.22.5
|
||||
|
||||
require (
|
||||
github.com/alibaba/sentinel-golang v1.0.4
|
||||
@ -12,7 +14,8 @@ require (
|
||||
github.com/bytedance/sonic v1.12.6
|
||||
github.com/casbin/casbin/v2 v2.77.2
|
||||
github.com/forgoer/openssl v1.6.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/gin-contrib/cors v1.7.3
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-admin-team/go-admin-core v1.5.2-0.20231103105356-84418ed9252c
|
||||
github.com/go-admin-team/go-admin-core/sdk v1.5.2-0.20231103105356-84418ed9252c
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
@ -44,8 +47,8 @@ require (
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||
github.com/xuri/excelize/v2 v2.9.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.29.0
|
||||
golang.org/x/net v0.31.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/net v0.33.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gorm.io/driver/mysql v1.5.2
|
||||
gorm.io/driver/postgres v1.5.4
|
||||
@ -71,7 +74,7 @@ require (
|
||||
github.com/andygrunwald/go-jira v1.16.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bsm/redislock v0.9.4 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chanxuehong/rand v0.0.0-20211009035549-2f07823e8e99 // indirect
|
||||
github.com/chanxuehong/wechat v0.0.0-20230222024006-36f0325263cd // indirect
|
||||
@ -83,7 +86,7 @@ require (
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/git-chglog/git-chglog v0.15.4 // indirect
|
||||
@ -98,9 +101,9 @@ require (
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.15.5 // indirect
|
||||
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
@ -119,9 +122,9 @@ require (
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kyokomi/emoji/v2 v2.2.11 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
@ -139,7 +142,7 @@ require (
|
||||
github.com/mojocn/base64Captcha v1.3.5 // indirect
|
||||
github.com/nsqio/go-nsq v1.1.0 // indirect
|
||||
github.com/nyaruka/phonenumbers v1.0.55 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
@ -160,7 +163,7 @@ require (
|
||||
github.com/trivago/tgo v1.0.7 // indirect
|
||||
github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/urfave/cli/v2 v2.24.3 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
@ -169,16 +172,16 @@ require (
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/arch v0.12.0 // indirect
|
||||
golang.org/x/image v0.18.0 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/term v0.26.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@ -74,3 +74,25 @@ type BinanceFutureOrder struct {
|
||||
SelfTradePreventionMode string `json:"selfTradePreventionMode"` // 订单自成交保护模式
|
||||
GoodTillDate int64 `json:"goodTillDate"` // 订单TIF为GTD时的自动取消时间
|
||||
}
|
||||
|
||||
type BinanceSpotAccount struct {
|
||||
Balances []BinanceSpotBalance `json:"balances"`
|
||||
}
|
||||
|
||||
type BinanceSpotBalance struct {
|
||||
Asset string `json:"asset"`
|
||||
Free string `json:"free"`
|
||||
Locked string `json:"locked"`
|
||||
}
|
||||
|
||||
type BinanceFutureBalance struct {
|
||||
AccountAlias string `json:"accountAlias"` // 账户唯一识别码
|
||||
Asset string `json:"asset"` // 资产
|
||||
Balance string `json:"balance"` // 总余额
|
||||
CrossWalletBalance string `json:"crossWalletBalance"` // 全仓余额
|
||||
CrossUnPnl string `json:"crossUnPnl"` // 全仓持仓未实现盈亏
|
||||
AvailableBalance string `json:"availableBalance"` // 下单可用余额
|
||||
MaxWithdrawAmount string `json:"maxWithdrawAmount"` // 最大可转出余额
|
||||
MarginAvailable bool `json:"marginAvailable"` // 是否可用作联合保证金
|
||||
UpdateTime int64 `json:"updateTime"` // 更新时间(时间戳)
|
||||
}
|
||||
|
||||
33
models/positiondto/cache.go
Normal file
33
models/positiondto/cache.go
Normal file
@ -0,0 +1,33 @@
|
||||
package positiondto
|
||||
|
||||
import "github.com/shopspring/decimal"
|
||||
|
||||
//持仓信息
|
||||
type PositionDto struct {
|
||||
SymbolType int `json:"symbolType"` //交易对类型 1-现货 2-合约
|
||||
Side string `json:"side"` //买卖方向 BUY SELL
|
||||
PositionSide string `json:"positionSide"` //持仓方向 LONG SHORT
|
||||
Quantity decimal.Decimal `json:"quantity"` //总数量
|
||||
TotalLoss decimal.Decimal `json:"totalLoss"` //总亏损
|
||||
Symbol string `json:"symbol"` //交易对
|
||||
ApiId int `json:"apiId"` //apiid
|
||||
LastPrice decimal.Decimal `json:"lastPrice"` //上一次成交价
|
||||
}
|
||||
|
||||
type PositionAddReq struct {
|
||||
SymbolType int `json:"symbolType"` //交易对类型 1-现货 2-合约
|
||||
Side string `json:"side"` //方向
|
||||
Quantity decimal.Decimal `json:"quantity"` //总数量
|
||||
Symbol string `json:"symbol"` //交易对
|
||||
ApiId int `json:"apiId"` //apiid
|
||||
Price decimal.Decimal `json:"price"` //本次成交价
|
||||
PositionSide string `json:"positionSide"` //持仓方向
|
||||
}
|
||||
|
||||
type LinePreOrderPositioinDelReq struct {
|
||||
SymbolType int `json:"symbolType"` //交易对类型 1-现货 2-合约
|
||||
Side string `json:"side"` //方向
|
||||
Symbol string `json:"symbol"` //交易对
|
||||
ApiId int `json:"apiId"` //apiid
|
||||
ExchangeType string `json:"exchangeType"` //交易所类型
|
||||
}
|
||||
@ -35,6 +35,19 @@ func NewInvite() *IntToStr {
|
||||
}
|
||||
}
|
||||
|
||||
// NewInvite 数字邀请码
|
||||
func NewNumberInvite() *IntToStr {
|
||||
return &IntToStr{
|
||||
SALT: 15151239, // 随意取一个数值
|
||||
Len: 9, // 邀请码长度
|
||||
PRIME2: 3, // 与邀请码长度 Len 互质
|
||||
AlphanumericSet: []rune{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
}, // 邀请码长度
|
||||
PRIME1: 3, // 与字符集长度 10 互质
|
||||
}
|
||||
}
|
||||
|
||||
func (in IntToStr) DeCode(codeStr string) int {
|
||||
code := make([]rune, 0, in.Len)
|
||||
var key rune = 0
|
||||
@ -90,6 +103,31 @@ func (in IntToStr) Encode(uid int) string {
|
||||
return string(code)
|
||||
}
|
||||
|
||||
func (i IntToStr) GenerateRandomCode(num int) string {
|
||||
// 用当前时间 + 随机数生成编码基础值
|
||||
rand.Seed(time.Now().UnixNano()) // Ensure randomness
|
||||
num = num + rand.Intn(10000) // 通过加入随机数,避免重复
|
||||
|
||||
// 对输入进行基础的模运算,避免直接按时间戳生成
|
||||
var result []rune
|
||||
for num > 0 {
|
||||
result = append(result, i.AlphanumericSet[num%len(i.AlphanumericSet)])
|
||||
num = num / len(i.AlphanumericSet)
|
||||
}
|
||||
|
||||
// 返回编码后的字符串,并保证字符串长度固定
|
||||
for len(result) < i.Len {
|
||||
result = append(result, i.AlphanumericSet[rand.Intn(len(i.AlphanumericSet))])
|
||||
}
|
||||
|
||||
// 将结果逆序,保证更好的随机性
|
||||
for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
|
||||
result[i], result[j] = result[j], result[i]
|
||||
}
|
||||
|
||||
return string(result)
|
||||
}
|
||||
|
||||
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
const smsLetters = "0123456789"
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ func CheckIsEmail(email string) bool {
|
||||
}
|
||||
|
||||
// SendFrontedEmail 发送邮件
|
||||
func SendFrontedEmail(toEmail string, code string) error {
|
||||
func SendFrontedEmail(toEmail string, code string, subject, body string) error {
|
||||
// 邮箱配置
|
||||
from := config.ExtConfig.EmailConfig.MailFrom // 发送者邮箱
|
||||
password := config.ExtConfig.EmailConfig.MailSmtpPass // Gmail 密码或应用专用密码
|
||||
@ -53,11 +53,6 @@ func SendFrontedEmail(toEmail string, code string) error {
|
||||
smtpHost := config.ExtConfig.EmailConfig.MailSmtpHost // Gmail SMTP 服务器
|
||||
smtpPort := config.ExtConfig.EmailConfig.MailSmtpPort // SMTP 端口
|
||||
|
||||
link := fmt.Sprintf("%s/verify?email=%s&verify_code=%s&type=register", config.ExtConfig.Domain, toEmail, code)
|
||||
// 创建邮件消息
|
||||
subject := "注册验证"
|
||||
body := fmt.Sprintf("<h1>注册验证</h1><p>您收到此电子邮件,用于进行邮箱验证,请点击下面的链接或打开下面的网址继续。 <p>You have received this email for email verification, please click the link below or open the URL below to continue.</p> %s </p>", link)
|
||||
|
||||
m := gomail.NewMessage()
|
||||
m.SetHeader("From", from) // 发件人
|
||||
m.SetHeader("To", to) // 收件人
|
||||
|
||||
@ -87,3 +87,16 @@ func DiscardDecimal(value decimal.Decimal, discardDigits int32) decimal.Decimal
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// SafeDiv 安全除法
|
||||
// dividend: 被除数
|
||||
// divisor: 除数
|
||||
func SafeDiv(dividend, divisor decimal.Decimal) decimal.Decimal {
|
||||
var result decimal.Decimal
|
||||
|
||||
if dividend.Cmp(decimal.Zero) != 0 && divisor.Cmp(decimal.Zero) != 0 {
|
||||
result = dividend.Div(divisor)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
59
pkg/utility/namehelper.go
Normal file
59
pkg/utility/namehelper.go
Normal file
@ -0,0 +1,59 @@
|
||||
package utility
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var adjectives = []string{
|
||||
"Swift", "Brave", "Clever", "Happy", "Lucky", "Mysterious", "Bold", "Fierce", "Noble", "Graceful",
|
||||
"Vivid", "Loyal", "Fearless", "Cunning", "Wise", "Radiant", "Silent", "Majestic", "Gentle", "Persistent",
|
||||
"Curious", "Agile", "Sharp", "Elegant", "Eager", "Vigorous", "Daring", "Mighty", "Witty", "Strong",
|
||||
"Bright", "Persistent", "Resilient", "Fearless", "Imaginative", "Creative", "Charming", "Playful", "Vigorous",
|
||||
"Passionate", "Dashing", "Resolute", "Adventurous", "Energetic", "Courageous",
|
||||
}
|
||||
|
||||
var animals = []string{
|
||||
"Tiger", "Panda", "Eagle", "Wolf", "Lion", "Fox", "Bear", "Falcon", "Shark", "Rabbit",
|
||||
"Elephant", "Zebra", "Cheetah", "Jaguar", "Leopard", "Giraffe", "Hawk", "Owl", "Dragon", "Whale",
|
||||
"Buffalo", "Panther", "Raven", "Vulture", "Bison", "Wolfhound", "Penguin", "Koala", "Coyote", "Crocodile",
|
||||
"Rhinoceros", "Kangaroo", "Camel", "Alligator", "Otter", "Squid", "Octopus", "Cheetah", "Lynx", "Mole",
|
||||
"Seagull", "Tiger Shark", "Wolverine", "Snow Leopard", "Bald Eagle",
|
||||
}
|
||||
|
||||
// 生成唯一昵称
|
||||
func GenerateUniqueNickname() (string, error) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
nickname := fmt.Sprintf("%s%s%s%s", // 形容词 + 动物名 + 随机字母 + 随机数字
|
||||
adjectives[rand.Intn(len(adjectives))],
|
||||
animals[rand.Intn(len(animals))],
|
||||
randomString(1), // 随机一个字母
|
||||
randomDigits(4), // 随机 4 个数字
|
||||
)
|
||||
|
||||
return nickname, fmt.Errorf("未能生成唯一昵称")
|
||||
}
|
||||
|
||||
// 随机生成字母
|
||||
func randomString(n int) string {
|
||||
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
result := make([]rune, n)
|
||||
for i := range result {
|
||||
result[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
// 随机生成数字
|
||||
func randomDigits(n int) string {
|
||||
digits := []rune("0123456789")
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
result := make([]rune, n)
|
||||
for i := range result {
|
||||
result[i] = digits[rand.Intn(len(digits))]
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
21
pkg/utility/urlhelper.go
Normal file
21
pkg/utility/urlhelper.go
Normal file
@ -0,0 +1,21 @@
|
||||
package utility
|
||||
|
||||
import "net/url"
|
||||
|
||||
func ParseURLParams(rawURL string) (map[string]string, error) {
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryParams := parsedURL.Query()
|
||||
result := make(map[string]string)
|
||||
|
||||
for key, values := range queryParams {
|
||||
if len(values) > 0 {
|
||||
result[key] = values[0] // 取第一个值
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
DbModels "go-admin/app/admin/models"
|
||||
"go-admin/app/admin/service/dto"
|
||||
"go-admin/common/const/rediskey"
|
||||
commondto "go-admin/common/dto"
|
||||
"go-admin/common/global"
|
||||
@ -229,10 +230,8 @@ func (e SpotRestApi) OrderPlace(orm *gorm.DB, params OrderPlacementService) erro
|
||||
paramsMaps["stopPrice"] = params.StopPrice.String()
|
||||
}
|
||||
}
|
||||
var apiUserInfo DbModels.LineApiUser
|
||||
|
||||
err := orm.Model(&DbModels.LineApiUser{}).Where("id = ?", params.ApiId).Find(&apiUserInfo).Error
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
apiUserInfo, err := GetApiInfo(params.ApiId)
|
||||
if apiUserInfo.Id == 0 {
|
||||
log.Errorf("api用户出错 err: %+v", err)
|
||||
return err
|
||||
}
|
||||
@ -272,6 +271,24 @@ func (e SpotRestApi) OrderPlace(orm *gorm.DB, params OrderPlacementService) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// 循环取消
|
||||
func (e SpotRestApi) CancelOpenOrdersLoop(orm *gorm.DB, req CancelOpenOrdersReq, retryCount int) error {
|
||||
err := e.CancelOpenOrders(orm, req)
|
||||
|
||||
if err != nil {
|
||||
for x := 1; x < retryCount; x++ {
|
||||
err = e.CancelOpenOrders(orm, req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(x) * 200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelOpenOrders 撤销单一交易对下所有挂单 包括了来自订单列表的挂单
|
||||
func (e SpotRestApi) CancelOpenOrders(orm *gorm.DB, req CancelOpenOrdersReq) error {
|
||||
if orm == nil {
|
||||
@ -284,19 +301,12 @@ func (e SpotRestApi) CancelOpenOrders(orm *gorm.DB, req CancelOpenOrdersReq) err
|
||||
params := map[string]string{
|
||||
"symbol": req.Symbol,
|
||||
}
|
||||
var apiUserInfo DbModels.LineApiUser
|
||||
apiUserInfo, err := GetApiInfo(req.ApiId)
|
||||
|
||||
err = orm.Model(&DbModels.LineApiUser{}).Where("id = ?", req.ApiId).Find(&apiUserInfo).Error
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
if apiUserInfo.Id == 0 {
|
||||
return fmt.Errorf("api_id:%d 交易对:%s api用户出错:%+v", apiUserInfo.Id, req.Symbol, err)
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, _, err = client.SendSpotAuth("/api/v3/openOrders", "DELETE", params)
|
||||
if err != nil {
|
||||
dataMap := make(map[string]interface{})
|
||||
@ -326,13 +336,7 @@ func (e SpotRestApi) CancelOpenOrderByOrderSn(apiUserInfo DbModels.LineApiUser,
|
||||
"origClientOrderId": newClientOrderId,
|
||||
"recvWindow": "10000",
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, code, err := client.SendSpotAuth("/api/v3/order", "DELETE", params)
|
||||
if err != nil || code != 200 {
|
||||
log.Error("取消现货委托失败 参数:", params)
|
||||
@ -588,3 +592,51 @@ func (e SpotRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo D
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// 获取现货U资产
|
||||
func GetSpotUProperty(apiUserInfo DbModels.LineApiUser, data *dto.LineUserPropertyResp) error {
|
||||
endpoint := "/api/v3/account"
|
||||
params := map[string]string{
|
||||
"omitZeroBalances": "true",
|
||||
}
|
||||
|
||||
balanceResp := binancedto.BinanceSpotAccount{}
|
||||
client := GetClient(&apiUserInfo)
|
||||
body, code, err := client.SendSpotAuth(endpoint, "GET", params)
|
||||
|
||||
if err != nil || code != 200 {
|
||||
log.Error("查询现货资产 参数:", params)
|
||||
log.Error("查询现货资产 code:", code)
|
||||
log.Error("查询现货资产 err:", err)
|
||||
dataMap := make(map[string]interface{})
|
||||
if err.Error() != "" {
|
||||
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
code, ok := dataMap["code"]
|
||||
if ok {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%s", apiUserInfo.Id, ErrorMaps[code.(float64)])
|
||||
}
|
||||
if strings.Contains(err.Error(), "Unknown order sent.") {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, ErrorMaps[-2011])
|
||||
}
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
|
||||
}
|
||||
|
||||
sonic.Unmarshal(body, &balanceResp)
|
||||
|
||||
if len(balanceResp.Balances) > 0 {
|
||||
for _, item := range balanceResp.Balances {
|
||||
if strings.ToUpper(item.Asset) == "USDT" {
|
||||
free := utility.StrToDecimal(item.Free)
|
||||
lock := utility.StrToDecimal(item.Locked)
|
||||
data.SpotFreeAmount = utility.StrToDecimal(item.Free)
|
||||
data.SpotTotalAmount = free.Add(lock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -9,7 +9,9 @@ import (
|
||||
"go-admin/common/global"
|
||||
"go-admin/common/helper"
|
||||
"go-admin/models"
|
||||
"go-admin/models/positiondto"
|
||||
"go-admin/pkg/utility"
|
||||
"go-admin/services/positionservice"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -410,3 +412,72 @@ func cancelSymbolTakeAndStop(db *gorm.DB, mainId int, symbolType int) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 保存仓位信息
|
||||
func savePosition(db *gorm.DB, preOrder *DbModels.LinePreOrder) positiondto.PositionDto {
|
||||
positionManage := positionservice.BinancePositionManagement{}
|
||||
positionManage.Orm = db
|
||||
positionReq := positiondto.PositionAddReq{
|
||||
ApiId: preOrder.ApiId,
|
||||
SymbolType: preOrder.SymbolType,
|
||||
Symbol: preOrder.Symbol,
|
||||
Price: utility.StrToDecimal(preOrder.Price),
|
||||
// Side: preOrder.Site,
|
||||
Quantity: utility.StrToDecimal(preOrder.Num),
|
||||
}
|
||||
|
||||
switch {
|
||||
case preOrder.OrderType == 0 && preOrder.Site == "BUY",
|
||||
preOrder.OrderType != 0 && preOrder.Site == "SELL":
|
||||
positionReq.PositionSide = "LONG"
|
||||
case preOrder.OrderType == 0 && preOrder.Site == "SELL",
|
||||
preOrder.OrderType != 0 && preOrder.Site == "BUY":
|
||||
positionReq.PositionSide = "SHORT"
|
||||
}
|
||||
|
||||
//减仓单 数量为负
|
||||
if preOrder.OrderType != 0 {
|
||||
if preOrder.Site == "BUY" {
|
||||
positionReq.Side = "SELL"
|
||||
} else {
|
||||
positionReq.Side = "BUY"
|
||||
}
|
||||
|
||||
positionReq.Quantity = positionReq.Quantity.Mul(decimal.NewFromInt(-1))
|
||||
} else {
|
||||
positionReq.Side = preOrder.Site
|
||||
}
|
||||
|
||||
positionData, err := positionManage.SavePosition(&positionReq, global.EXCHANGE_BINANCE)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("保存持仓信息失败, 主单号:%s, 错误信息:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
return positionData
|
||||
}
|
||||
|
||||
// 获取已开仓的主单id
|
||||
func getOpenPositionMainOrderId(db *gorm.DB, newId, apiId, symbolType int, exchangeType, symbol, side string) ([]DbModels.LinePreOrder, error) {
|
||||
mainOrders := make([]DbModels.LinePreOrder, 0)
|
||||
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).
|
||||
Where("api_id =? AND status>4 AND order_type =0 AND status<7 AND symbol=? AND symbol_type =? AND site= ? AND exchange_type=? AND id!=?",
|
||||
apiId, symbol, symbolType, side, exchangeType, newId).
|
||||
Select("id", "main_id", "order_sn").Find(&mainOrders).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mainOrders, nil
|
||||
}
|
||||
|
||||
// 获取需要取消的订单号
|
||||
func GetOpenOrderSns(db *gorm.DB, mainIds []int) ([]string, error) {
|
||||
result := []string{}
|
||||
|
||||
//委托中的订单
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id IN ? AND status=5", mainIds).Select("order_sn").Find(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@ -467,8 +467,7 @@ func (e FutRestApi) OrderPlace(orm *gorm.DB, params FutOrderPlace) error {
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
var paramsMaps map[string]string
|
||||
paramsMaps = map[string]string{
|
||||
paramsMaps := map[string]string{
|
||||
"symbol": params.Symbol,
|
||||
"side": params.Side,
|
||||
"quantity": params.Quantity.String(),
|
||||
@ -519,18 +518,11 @@ func (e FutRestApi) OrderPlace(orm *gorm.DB, params FutOrderPlace) error {
|
||||
paramsMaps["positionSide"] = "LONG"
|
||||
}
|
||||
}
|
||||
var apiUserInfo DbModels.LineApiUser
|
||||
err := orm.Model(&DbModels.LineApiUser{}).Where("id = ?", params.ApiId).Find(&apiUserInfo).Error
|
||||
apiUserInfo, err := GetApiInfo(params.ApiId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, statusCode, err := client.SendFuturesRequestAuth("/fapi/v1/order", "POST", paramsMaps)
|
||||
if err != nil {
|
||||
var dataMap map[string]interface{}
|
||||
@ -662,12 +654,7 @@ func getSymbolHolde(e FutRestApi, apiInfo *DbModels.LineApiUser, symbol string,
|
||||
}
|
||||
|
||||
func (e FutRestApi) GetPositionV3(apiUserInfo *DbModels.LineApiUser, symbol string) ([]PositionRisk, error) {
|
||||
var client *helper.BinanceClient
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(apiUserInfo)
|
||||
params := map[string]string{
|
||||
"symbol": symbol,
|
||||
"recvWindow": "5000",
|
||||
@ -736,12 +723,7 @@ func (e FutRestApi) ClosePosition(symbol string, orderSn string, quantity decima
|
||||
params["timeInForce"] = "GTC"
|
||||
}
|
||||
|
||||
var client *helper.BinanceClient
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
|
||||
resp, _, err := client.SendFuturesRequestAuth(endpoint, "POST", params)
|
||||
if err != nil {
|
||||
@ -781,12 +763,7 @@ func (e FutRestApi) CancelFutOrder(apiUserInfo DbModels.LineApiUser, symbol stri
|
||||
"symbol": symbol, //交易对
|
||||
"origClientOrderId": newClientOrderId, //用户自定义订单号
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, _, err := client.SendFuturesRequestAuth(endpoint, "DELETE", params)
|
||||
if err != nil {
|
||||
var dataMap map[string]interface{}
|
||||
@ -815,12 +792,7 @@ func (e FutRestApi) CancelAllFutOrder(apiUserInfo DbModels.LineApiUser, symbol s
|
||||
"symbol": symbol, //交易对
|
||||
"recvWindow": "5000",
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, _, err := client.SendFuturesRequestAuth(endpoint, "DELETE", params)
|
||||
if err != nil {
|
||||
var dataMap map[string]interface{}
|
||||
@ -854,12 +826,7 @@ func (e FutRestApi) CancelBatchFutOrder(apiUserInfo DbModels.LineApiUser, symbol
|
||||
"symbol": symbol, //交易对
|
||||
"origClientOrderIdList": string(marshal),
|
||||
}
|
||||
var client *helper.BinanceClient
|
||||
if apiUserInfo.UserPass == "" {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "", apiUserInfo.IpAddress)
|
||||
} else {
|
||||
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
|
||||
}
|
||||
client := GetClient(&apiUserInfo)
|
||||
_, code, err := client.SendFuturesRequestAuth(endpoint, "DELETE", params)
|
||||
if err != nil {
|
||||
log.Error("取消合约委托失败 参数:", params)
|
||||
@ -893,8 +860,8 @@ func (e FutRestApi) CalcSymbolExchangeAmt(symbol string, quoteSymbol string, tot
|
||||
tickerSymbol := helper.DefaultRedis.Get(rediskey.FutSymbolTicker).Val()
|
||||
tickerSymbolMaps := make([]dto.Ticker, 0)
|
||||
sonic.Unmarshal([]byte(tickerSymbol), &tickerSymbolMaps)
|
||||
var targetSymbol string
|
||||
targetSymbol = strings.Replace(symbol, quoteSymbol, "USDT", 1) //ETHBTC -》 ETHUSDT
|
||||
|
||||
targetSymbol := strings.Replace(symbol, quoteSymbol, "USDT", 1) //ETHBTC -》 ETHUSDT
|
||||
key := fmt.Sprintf("%s:%s", global.TICKER_FUTURES, targetSymbol)
|
||||
tradeSet, _ := helper.GetObjString[models.TradeSet](helper.DefaultRedis, key)
|
||||
var targetPrice decimal.Decimal
|
||||
@ -908,11 +875,6 @@ func (e FutRestApi) CalcSymbolExchangeAmt(symbol string, quoteSymbol string, tot
|
||||
return quantity
|
||||
}
|
||||
|
||||
// 加仓主账号
|
||||
func (e FutRestApi) CoverAccountA(apiUserInfo DbModels.LineApiUser, symbol string) {
|
||||
|
||||
}
|
||||
|
||||
// GetFutSymbolLastPrice 获取现货交易对最新价格
|
||||
func (e FutRestApi) GetFutSymbolLastPrice(targetSymbol string) (lastPrice decimal.Decimal) {
|
||||
key := fmt.Sprintf(global.TICKER_FUTURES, global.EXCHANGE_BINANCE, targetSymbol)
|
||||
@ -979,7 +941,7 @@ func (e FutRestApi) GetOrderByOrderSn(symbol, orderSn string, apiUserInfo DbMode
|
||||
}
|
||||
|
||||
/*
|
||||
查询现货委托
|
||||
查询合约委托
|
||||
*/
|
||||
// 根据订单号获取订单信息,如果获取失败,则进行重试
|
||||
func (e FutRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo DbModels.LineApiUser, retryCount int) (order binancedto.BinanceFutureOrder, err error) {
|
||||
@ -1000,3 +962,49 @@ func (e FutRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo Db
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// 获取合约U资产
|
||||
func GetFuturesUProperty(apiUserInfo DbModels.LineApiUser, data *dto.LineUserPropertyResp) error {
|
||||
endpoint := "/fapi/v3/balance"
|
||||
params := map[string]string{
|
||||
"recvWindow": "5000",
|
||||
}
|
||||
|
||||
balanceResp := make([]binancedto.BinanceFutureBalance, 0)
|
||||
client := GetClient(&apiUserInfo)
|
||||
body, code, err := client.SendFuturesAuth(endpoint, "GET", params)
|
||||
|
||||
if err != nil || code != 200 {
|
||||
log.Error("查询合约资产 参数:", params)
|
||||
log.Error("查询合约资产 code:", code)
|
||||
log.Error("查询合约资产 err:", err)
|
||||
dataMap := make(map[string]interface{})
|
||||
if err.Error() != "" {
|
||||
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
code, ok := dataMap["code"]
|
||||
if ok {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%s", apiUserInfo.Id, ErrorMaps[code.(float64)])
|
||||
}
|
||||
if strings.Contains(err.Error(), "Unknown order sent.") {
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, ErrorMaps[-2011])
|
||||
}
|
||||
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
|
||||
}
|
||||
|
||||
sonic.Unmarshal(body, &balanceResp)
|
||||
|
||||
for _, v := range balanceResp {
|
||||
if v.Asset == "USDT" {
|
||||
free := utility.StrToDecimal(v.AvailableBalance)
|
||||
|
||||
data.FuturesFreeAmount = free
|
||||
data.FuturesTotalAmount = utility.StrToDecimal(v.Balance)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -87,13 +87,6 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi
|
||||
return
|
||||
}
|
||||
|
||||
//判断是否有已触发交易对
|
||||
count, _ := GetSymbolTriggerCount(db, v.Symbol, v.ApiId, 2)
|
||||
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
price, _ := decimal.NewFromString(v.Price)
|
||||
num, _ := decimal.NewFromString(preOrder.Num)
|
||||
|
||||
@ -208,8 +201,8 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, futApi FutRes
|
||||
return
|
||||
} else if ok {
|
||||
defer lock.Release()
|
||||
takeOrder := DbModels.LinePreOrder{}
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type =1", reduceOrder.Pid).Find(&takeOrder).Error; err != nil {
|
||||
takeOrders := make([]DbModels.LinePreOrder, 0)
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_type =1 AND status IN (1,5)", reduceOrder.MainId).Find(&takeOrders).Error; err != nil {
|
||||
log.Error("查询止盈单失败")
|
||||
return
|
||||
}
|
||||
@ -221,19 +214,20 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, futApi FutRes
|
||||
return
|
||||
}
|
||||
|
||||
apiInfo, _ := GetApiInfo(takeOrder.ApiId)
|
||||
apiInfo, _ := GetApiInfo(reduceOrder.ApiId)
|
||||
|
||||
if apiInfo.Id == 0 {
|
||||
log.Error("现货减仓 查询api用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
for _, takeOrder := range takeOrders {
|
||||
err := CancelFutOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn)
|
||||
|
||||
if err != nil {
|
||||
log.Error("合约止盈撤单失败", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
price := reduceOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.ReducePremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit))
|
||||
num := reduceOrder.Num.Truncate(int32(tradeSet.AmountDigit))
|
||||
|
||||
@ -93,13 +93,16 @@ func handleFutOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderSta
|
||||
switch {
|
||||
//主单成交
|
||||
case preOrder.OrderType == 0 && orderStatus == 6:
|
||||
handleFutMainOrderFilled(db, preOrder)
|
||||
handleFutMainOrderFilled(db, preOrder, preOrder.Id, true)
|
||||
//止盈成交
|
||||
case preOrder.OrderType == 1 && orderStatus == 6:
|
||||
handleTakeProfit(db, preOrder)
|
||||
//减仓回调
|
||||
case preOrder.OrderType == 4 && orderStatus == 6:
|
||||
handleReduceFilled(db, preOrder)
|
||||
//主单取消
|
||||
case preOrder.OrderType == 0 && preOrder.Pid == 0 && orderStatus == 4:
|
||||
handleMainOrderCancel(db, preOrder, 2)
|
||||
//止损成交
|
||||
case preOrder.OrderType == 2 && orderStatus == 6:
|
||||
handleStopLoss(db, preOrder)
|
||||
@ -127,83 +130,105 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
logger.Errorf("handleReduceFilled 获取交易对设置失败,订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
}
|
||||
rate := utility.StringAsFloat(preOrder.Rate)
|
||||
|
||||
price := utility.StrToDecimal(preOrder.Price)
|
||||
parentOrder, err := GetOrderById(db, preOrder.Pid)
|
||||
// 100%减仓 终止流程
|
||||
if rate >= 100 {
|
||||
//缓存
|
||||
removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn)
|
||||
removePosition(db, preOrder)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleReduceFilled 获取主单失败,订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
ids := []int{preOrder.MainId, preOrder.Pid}
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id IN ? AND status =6", ids).Update("status", 9).Error; err != nil {
|
||||
logger.Info("100%减仓完毕,终结流程")
|
||||
}
|
||||
parentPrice := utility.StrToDecimal(parentOrder.Price)
|
||||
num := utility.StrToDecimal(preOrder.Num)
|
||||
lossAmount := price.Sub(parentPrice).Abs().Mul(num).Truncate(int32(tradeSet.PriceDigit))
|
||||
|
||||
if !strings.HasSuffix(preOrder.Symbol, "USDT") {
|
||||
tradeSetU, err := GetTradeSet(utility.ReplaceSuffix(preOrder.Symbol, preOrder.QuoteSymbol, ""), 1)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取币本位对应U交易对设置失败,订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
}
|
||||
|
||||
lossAmount = lossAmount.Mul(utility.StrToDecimal(tradeSetU.LastPrice)).Truncate(int32(tradeSetU.PriceDigit))
|
||||
}
|
||||
|
||||
if err := db.Model(&parentOrder).Where("loss_amount = ?", 0).Update("loss_amount", lossAmount).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 更新亏损金额失败,订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
}
|
||||
|
||||
positionData := savePosition(db, preOrder)
|
||||
orders := make([]models.LinePreOrder, 0)
|
||||
if err := db.Model(&models.LinePreOrder{}).Where("pid =? AND order_type IN (1,2) AND status = 0", preOrder.Id).Find(&orders).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取待触发订单失败,订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
}
|
||||
|
||||
orderExt := models.LinePreOrderExt{}
|
||||
totalNum := getFuturesPositionAvailableQuantity(db, apiUserInfo, preOrder, tradeSet)
|
||||
totalNum = totalNum.Truncate(int32(tradeSet.AmountDigit))
|
||||
price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit))
|
||||
futApi := FutRestApi{}
|
||||
mainId := preOrder.Id
|
||||
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
db.Model(&orderExt).Where("order_id =?", preOrder.Pid).First(&orderExt)
|
||||
|
||||
for _, v := range orders {
|
||||
if v.OrderType == 1 {
|
||||
//亏损大于0 重新计算比例
|
||||
if positionData.TotalLoss.Cmp(decimal.Zero) > 0 && orderExt.Id > 0 {
|
||||
percentag := positionData.TotalLoss.Div(totalNum).Div(price).Mul(decimal.NewFromInt(100))
|
||||
percentag = percentag.Add(orderExt.TakeProfitRatio).Truncate(2)
|
||||
v.Rate = percentag.String()
|
||||
percentag = percentag.Div(decimal.NewFromInt(100))
|
||||
|
||||
if positionData.PositionSide == "LONG" {
|
||||
v.Price = price.Mul(decimal.NewFromInt(1).Add(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
} else {
|
||||
v.Price = price.Mul(decimal.NewFromInt(1).Sub(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
}
|
||||
}
|
||||
|
||||
processFutTakeProfitOrder(db, futApi, v, totalNum)
|
||||
} else if v.OrderType == 2 {
|
||||
processFutStopLossOrder(db, v, utility.StrToDecimal(v.Price), totalNum)
|
||||
}
|
||||
}
|
||||
nextFuturesReduceTrigger(db, mainId, totalNum, tradeSet)
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrder := DbModels.LinePreOrder{}
|
||||
// 下一个合约待触发
|
||||
func nextFuturesReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, tradeSet models2.TradeSet) {
|
||||
nextOrder := DbModels.LinePreOrder{}
|
||||
nextExt := DbModels.LinePreOrderExt{}
|
||||
|
||||
if err := db.Model(&addPositionOrder).Where("main_id =? AND order_category=3 AND status=0", preOrder.MainId).First(&addPositionOrder).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
if err := db.Model(&models.LinePreOrder{}).Where("main_id =? AND order_type =4 AND status=0", mainId).Order("rate asc").First(&nextOrder).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
keyFutAddpositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE)
|
||||
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
if err := db.Model(&models.LinePreOrderExt{}).Where("order_id =? and add_type =2", nextOrder.Id).First(&nextExt).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
num := totalNum
|
||||
//移除缓存
|
||||
key := fmt.Sprintf(rediskey.FuturesReduceList, global.EXCHANGE_BINANCE)
|
||||
vals, _ := helper.DefaultRedis.GetAllList(key)
|
||||
item := ReduceListItem{}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
for _, val := range vals {
|
||||
sonic.Unmarshal([]byte(val), &item)
|
||||
if item.MainId == mainId {
|
||||
if _, err := helper.DefaultRedis.LRem(key, val); err != nil {
|
||||
logger.Errorf("减仓单 redis删除失败 main_id:%v err:%v", mainId, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keyFutAddpositionKey, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
//
|
||||
if nextExt.AddPositionVal.Cmp(decimal.Zero) > 0 && nextExt.AddPositionVal.Cmp(decimal.Zero) < 100 {
|
||||
// 计算减仓数量
|
||||
num = totalNum.Mul(nextExt.AddPositionVal.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
nextOrder.Num = num.String()
|
||||
|
||||
if err := db.Model(&nextOrder).Update("num", nextOrder.Num).Error; err != nil {
|
||||
logger.Errorf("更新减仓单数量失败 err:%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
processFutReduceOrder(nextOrder, utility.StrToDecimal(nextOrder.Price).Truncate(int32(tradeSet.PriceDigit)), num)
|
||||
}
|
||||
|
||||
// 获取合约可用数量
|
||||
@ -255,10 +280,10 @@ func getFuturesPositionNum(apiUserInfo DbModels.LineApiUser, preOrder *DbModels.
|
||||
positionAmt := utility.StrToDecimal(item.PositionAmt)
|
||||
|
||||
//多
|
||||
if positionAmt.Cmp(decimal.Zero) > 0 && preOrder.Site == "SELL" {
|
||||
if positionAmt.Cmp(decimal.Zero) > 0 && ((preOrder.OrderType == 0 && preOrder.Site == "BUY") || (preOrder.OrderType != 0 && preOrder.Site == "SELL")) {
|
||||
num = positionAmt.Abs().Truncate(int32(tradeSet.AmountDigit))
|
||||
break
|
||||
} else if positionAmt.Cmp(decimal.Zero) < 0 && preOrder.Site == "BUY" {
|
||||
} else if positionAmt.Cmp(decimal.Zero) < 0 && ((preOrder.OrderType != 0 && preOrder.Site == "BUY") || (preOrder.OrderType == 0 && preOrder.Site == "SELL")) {
|
||||
//空
|
||||
num = positionAmt.Abs().Truncate(int32(tradeSet.AmountDigit))
|
||||
break
|
||||
@ -275,14 +300,15 @@ func getFuturesPositionNum(apiUserInfo DbModels.LineApiUser, preOrder *DbModels.
|
||||
|
||||
// 平仓单成交
|
||||
func handleClosePosition(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
removeFutLossAndAddPosition(preOrder)
|
||||
removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn)
|
||||
removePosition(db, preOrder)
|
||||
|
||||
futApi := FutRestApi{}
|
||||
apiUserInfo, _ := GetApiInfo(preOrder.ApiId)
|
||||
|
||||
if apiUserInfo.Id > 0 {
|
||||
if err := futApi.CancelAllFutOrder(apiUserInfo, preOrder.Symbol); err != nil {
|
||||
logger.Errorf("止盈单成功 取消其它订单失败 订单号:%s:", err)
|
||||
mainIds := []int{preOrder.MainId}
|
||||
if err := cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, false); err != nil {
|
||||
logger.Errorf("平仓单成功 取消其它订单失败 订单号:%s:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,18 +321,15 @@ func handleClosePosition(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
|
||||
// 止损单成交
|
||||
func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
removeFutLossAndAddPosition(preOrder)
|
||||
removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn)
|
||||
removePosition(db, preOrder)
|
||||
|
||||
spotApi := SpotRestApi{}
|
||||
apiUserInfo, _ := GetApiInfo(preOrder.ApiId)
|
||||
|
||||
if apiUserInfo.Id > 0 {
|
||||
req := CancelOpenOrdersReq{
|
||||
Symbol: preOrder.Symbol,
|
||||
ApiId: preOrder.ApiId,
|
||||
}
|
||||
if err := spotApi.CancelOpenOrders(db, req); err != nil {
|
||||
logger.Errorf("止盈单成功 取消其它订单失败 订单号:%s:", err)
|
||||
mainIds := []int{preOrder.MainId}
|
||||
if err := cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, false); err != nil {
|
||||
logger.Errorf("止损单成功 取消其它订单失败 订单号:%s:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,14 +342,22 @@ func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
|
||||
// 止盈单成交
|
||||
func handleTakeProfit(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
removeFutLossAndAddPosition(preOrder)
|
||||
childCount, _ := GetChildTpOrder(db, preOrder.Id)
|
||||
|
||||
if childCount > 0 {
|
||||
extOrderId := preOrder.Pid //ext主单id
|
||||
|
||||
handleFutMainOrderFilled(db, preOrder, extOrderId, false)
|
||||
} else {
|
||||
removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn)
|
||||
removePosition(db, preOrder)
|
||||
|
||||
futApi := FutRestApi{}
|
||||
apiUserInfo, _ := GetApiInfo(preOrder.ApiId)
|
||||
|
||||
if apiUserInfo.Id > 0 {
|
||||
if err := futApi.CancelAllFutOrder(apiUserInfo, preOrder.Symbol); err != nil {
|
||||
logger.Errorf("止盈单成功 取消其它订单失败 订单号:%s:", err)
|
||||
mainIds := []int{preOrder.MainId}
|
||||
if err := cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, false); err != nil {
|
||||
logger.Errorf("止损单成功 取消其它订单失败 订单号:%s:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,10 +366,11 @@ func handleTakeProfit(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id IN ? AND order_type=0", ids).Update("status", 9).Error; err != nil {
|
||||
logger.Errorf("主单止盈成功修改主单状态失败 订单号:%s:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除合约缓存
|
||||
func removeFutLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
|
||||
func removeFutLossAndAddPosition(mainId int, orderSn string) {
|
||||
stoplossKey := fmt.Sprintf(rediskey.FuturesStopLossList, global.EXCHANGE_BINANCE)
|
||||
stoplossVal, _ := helper.DefaultRedis.GetAllList(stoplossKey)
|
||||
addPositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE)
|
||||
@ -352,11 +384,11 @@ func removeFutLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
|
||||
//止损缓存
|
||||
for _, v := range stoplossVal {
|
||||
sonic.Unmarshal([]byte(v), &stoploss)
|
||||
if stoploss.MainId == preOrder.MainId {
|
||||
if stoploss.MainId == mainId {
|
||||
_, err := helper.DefaultRedis.LRem(stoplossKey, v)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除止损缓存失败:%v", preOrder.OrderSn, err)
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除止损缓存失败:%v", orderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -364,11 +396,11 @@ func removeFutLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
|
||||
//加仓缓存
|
||||
for _, v := range addPositionVal {
|
||||
sonic.Unmarshal([]byte(v), &addPosition)
|
||||
if addPosition.MainId == preOrder.MainId {
|
||||
if addPosition.MainId == mainId {
|
||||
_, err := helper.DefaultRedis.LRem(addPositionKey, v)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除加仓缓存失败:%v", preOrder.OrderSn, err)
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除加仓缓存失败:%v", orderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -376,85 +408,257 @@ func removeFutLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
|
||||
//减仓缓存
|
||||
for _, v := range reduceVal {
|
||||
sonic.Unmarshal([]byte(v), &reduce)
|
||||
if reduce.MainId == preOrder.MainId {
|
||||
if reduce.MainId == mainId {
|
||||
_, err := helper.DefaultRedis.LRem(reduceKey, v)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除减仓缓存失败:%v", preOrder.OrderSn, err)
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除减仓缓存失败:%v", orderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 主单成交 处理止盈止损订单
|
||||
// preOrder 主单
|
||||
func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) {
|
||||
orders := []models.LinePreOrder{}
|
||||
tradeSet, _ := GetTradeSet(preOrder.Symbol, 1)
|
||||
|
||||
if tradeSet.Coin == "" {
|
||||
logger.Error("获取交易对失败")
|
||||
// 处理主单成交,处理止盈、止损、减仓订单
|
||||
func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrderId int, first bool) {
|
||||
// 获取交易对配置和API信息
|
||||
tradeSet, err := GetTradeSet(preOrder.Symbol, 1)
|
||||
mainId := preOrder.Id
|
||||
if err != nil || tradeSet.Coin == "" {
|
||||
logger.Errorf("获取交易对配置失败, 回调订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
if tradeSet.Coin == "" {
|
||||
logger.Errorf("获取交易对配置失败, 回调订单号:%s", preOrder.OrderSn)
|
||||
return
|
||||
}
|
||||
|
||||
if preOrder.OrderCategory == 3 {
|
||||
if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id = ?", preOrder.MainId).Update("add_position_status", 1).Error; err != nil {
|
||||
logger.Errorf("更新主单加仓状态失败, 主单号:%s, 错误信息:%v", preOrder.MainId, err)
|
||||
}
|
||||
|
||||
if err := cancelSymbolTakeAndStop(db, preOrder.MainId, preOrder.SymbolType); err != nil {
|
||||
logger.Errorf("取消止盈止损订单失败 orderSn:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
}
|
||||
apiInfo, err := GetApiInfo(preOrder.ApiId)
|
||||
if apiInfo.Id == 0 {
|
||||
logger.Error("订单回调查询apiuserinfo失败 err:", err)
|
||||
return
|
||||
}
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).
|
||||
Where("pid = ? AND order_type > 0 AND status = '0' ", preOrder.Id).
|
||||
Find(&orders).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
logger.Error("订单回调查询止盈止损单失败:", err)
|
||||
if err != nil || apiInfo.Id == 0 {
|
||||
logger.Errorf("订单回调查询apiuserinfo失败, 订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
futApi := FutRestApi{}
|
||||
num := getFuturesPositionAvailableQuantity(db, apiInfo, preOrder, tradeSet)
|
||||
num = num.Truncate(int32(tradeSet.AmountDigit))
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
// 处理主单加仓
|
||||
if preOrder.OrderCategory == 3 {
|
||||
if err := handleMainOrderAddPosition(db, preOrder); err != nil {
|
||||
logger.Errorf("处理主单加仓失败, 主单号:%s, 错误信息: %v", preOrder.MainId, err)
|
||||
return
|
||||
}
|
||||
} else if first {
|
||||
// 处理其他主单逻辑
|
||||
if err := cancelPositionOtherOrders(apiInfo, db, preOrder, true); err != nil {
|
||||
logger.Errorf("取消主单相关订单失败, 订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrders := make([]DbModels.LinePreOrder, 0)
|
||||
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_category=3 AND order_type=0 AND status=0", preOrder.Id).Order("rate asc").Find(&addPositionOrders).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
keyFutAddpositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE)
|
||||
|
||||
for _, addPositionOrder := range addPositionOrders {
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keyFutAddpositionKey, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取止盈止损订单
|
||||
orders, err := getStopOrders(db, preOrder)
|
||||
if err != nil {
|
||||
logger.Errorf("查询止盈止损订单失败, 订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取和保存持仓数据
|
||||
positionData := savePosition(db, preOrder)
|
||||
orderExt := models.LinePreOrderExt{}
|
||||
db.Model(&orderExt).Where("order_id =?", extOrderId).First(&orderExt)
|
||||
totalNum := getFuturesPositionAvailableQuantity(db, apiInfo, preOrder, tradeSet).Truncate(int32(tradeSet.AmountDigit))
|
||||
|
||||
// 更新订单数量并处理止盈、止损、减仓
|
||||
for _, order := range orders {
|
||||
price := utility.StrToDecimal(order.Price).Truncate(int32(tradeSet.PriceDigit))
|
||||
order.Price = price.String()
|
||||
|
||||
if order.OrderType == 4 {
|
||||
ext := DbModels.LinePreOrderExt{}
|
||||
db.Model(&ext).Where("order_id=?", preOrder.Id).Find(&ext)
|
||||
// 更新止盈止损订单数量
|
||||
num := updateOrderQuantity(db, order, preOrder, &orderExt, totalNum, first, tradeSet)
|
||||
|
||||
if ext.ReduceNumRatio.Cmp(decimal.Zero) > 0 {
|
||||
num = num.Mul(ext.ReduceNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
// 根据订单类型处理
|
||||
switch order.OrderType {
|
||||
case 1: // 止盈
|
||||
//亏损大于0 重新计算比例
|
||||
if first && positionData.TotalLoss.Cmp(decimal.Zero) > 0 && orderExt.Id > 0 {
|
||||
percentag := positionData.TotalLoss.Div(num).Div(price).Mul(decimal.NewFromInt(100))
|
||||
percentag = percentag.Add(orderExt.TakeProfitRatio).Truncate(2)
|
||||
order.Rate = percentag.String()
|
||||
percentag = percentag.Div(decimal.NewFromInt(100))
|
||||
|
||||
if positionData.PositionSide == "LONG" {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Add(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
} else {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Sub(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
}
|
||||
} else if !first && orderExt.TpTpPriceRatio.Cmp(decimal.Zero) > 0 {
|
||||
//止盈后止盈
|
||||
order.Rate = orderExt.TpTpPriceRatio.String()
|
||||
|
||||
if positionData.PositionSide == "LONG" {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Add(orderExt.TpTpPriceRatio.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
} else {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Sub(orderExt.TpTpPriceRatio.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
}
|
||||
}
|
||||
|
||||
processFutTakeProfitOrder(db, FutRestApi{}, order, num)
|
||||
case 2: // 止损
|
||||
if !first && orderExt.TpSlPriceRatio.Cmp(decimal.Zero) > 0 {
|
||||
//止盈后止损
|
||||
order.Rate = orderExt.TpSlPriceRatio.String()
|
||||
|
||||
if positionData.PositionSide == "LONG" {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Sub(orderExt.TpSlPriceRatio.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
} else {
|
||||
order.Price = price.Mul(decimal.NewFromInt(1).Add(orderExt.TpSlPriceRatio.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||
}
|
||||
}
|
||||
|
||||
processFutStopLossOrder(db, order, price, num)
|
||||
// case 4: // 减仓
|
||||
// processFutReduceOrder(order, price, num)
|
||||
}
|
||||
}
|
||||
|
||||
nextFuturesReduceTrigger(db, mainId, totalNum, tradeSet)
|
||||
}
|
||||
|
||||
// 处理主单加仓
|
||||
func handleMainOrderAddPosition(db *gorm.DB, preOrder *models.LinePreOrder) error {
|
||||
// 更新加仓状态
|
||||
if err := db.Model(&DbModels.LinePreOrderStatus{}).
|
||||
Where("order_id = ?", preOrder.MainId).
|
||||
Update("add_position_status", 1).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 取消止盈止损订单
|
||||
return cancelSymbolTakeAndStop(db, preOrder.MainId, preOrder.SymbolType)
|
||||
}
|
||||
|
||||
// 取消主单相关订单
|
||||
// changeMainOrderStatus 是否修改主单状态
|
||||
func cancelPositionOtherOrders(apiUserInfo DbModels.LineApiUser, db *gorm.DB, preOrder *models.LinePreOrder, changeMainOrderStatus bool) error {
|
||||
mainOrders, err := getOpenPositionMainOrderId(db, preOrder.Id, preOrder.ApiId, preOrder.SymbolType, preOrder.ExchangeType, preOrder.Symbol, preOrder.Site)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(mainOrders) == 0 {
|
||||
logger.Infof("主单没有持仓,不需要取消其他订单 sn:%s", preOrder.OrderSn)
|
||||
}
|
||||
|
||||
mainIds := []int{}
|
||||
for _, mainOrder := range mainOrders {
|
||||
mainId := mainOrder.Id
|
||||
|
||||
if mainOrder.MainId > 0 {
|
||||
mainId = mainOrder.MainId
|
||||
}
|
||||
removeFutLossAndAddPosition(mainId, mainOrder.OrderSn)
|
||||
|
||||
if !utility.ContainsInt(mainIds, mainId) {
|
||||
mainIds = append(mainIds, mainId)
|
||||
}
|
||||
}
|
||||
|
||||
// 批量取消订单
|
||||
|
||||
err = cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, changeMainOrderStatus)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 根据mainid 取消订单
|
||||
// @changeMainOrderStatus 是否更新主单状态
|
||||
func cancelMainOrders(mainIds []int, db *gorm.DB, apiUserInfo DbModels.LineApiUser, symbol string, changeMainOrderStatus bool) error {
|
||||
if len(mainIds) > 0 {
|
||||
orderSns, err := GetOpenOrderSns(db, mainIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
orderArray := utility.SplitSlice(orderSns, 10)
|
||||
futApi := FutRestApi{}
|
||||
for _, item := range orderArray {
|
||||
err := futApi.CancelBatchFutOrder(apiUserInfo, symbol, item)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("批量取消订单失败 orderSns:%v", item)
|
||||
}
|
||||
}
|
||||
|
||||
//需要修改主单状态
|
||||
if changeMainOrderStatus {
|
||||
if err := db.Exec("UPDATE line_pre_order SET `status`=4, `desc`=CONCAT(`desc`, ' 新单触发取消') WHERE id IN ? AND `status` =6", mainIds).Error; err != nil {
|
||||
logger.Errorf("合约 新下单成功后更新主单取消状态失败, 交易对:%s, 错误信息:%v", symbol, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取止盈止损订单
|
||||
func getStopOrders(db *gorm.DB, preOrder *models.LinePreOrder) ([]models.LinePreOrder, error) {
|
||||
var orders []models.LinePreOrder
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).
|
||||
Where("pid = ? AND order_type > 0 AND status = '0' ", preOrder.Id).
|
||||
Find(&orders).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
// 更新订单数量
|
||||
func updateOrderQuantity(db *gorm.DB, order models.LinePreOrder, preOrder *models.LinePreOrder, ext *models.LinePreOrderExt, num decimal.Decimal, first bool, tradeSet models2.TradeSet) decimal.Decimal {
|
||||
// 处理减仓比例
|
||||
// if order.OrderType == 4 && ext.ReduceNumRatio.Cmp(decimal.Zero) > 0 {
|
||||
// // 计算减仓数量
|
||||
// num = num.Mul(ext.ReduceNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
// order.Num = num.String()
|
||||
// } else
|
||||
|
||||
if first && (order.OrderCategory == 1 || order.OrderCategory == 3) && order.OrderType == 1 && ext.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && ext.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 {
|
||||
// 计算止盈数量
|
||||
num = num.Mul(ext.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
order.Num = num.String()
|
||||
}
|
||||
}
|
||||
|
||||
// 更新订单数量
|
||||
if err := db.Model(&order).Update("num", num).Error; err != nil {
|
||||
logger.Errorf("修改止盈止损数量失败 订单号:%s err:%v", order.OrderSn, err)
|
||||
}
|
||||
|
||||
logger.Errorf("止盈止损 下单数量:%v", num)
|
||||
switch order.OrderType {
|
||||
case 1: // 止盈
|
||||
processFutTakeProfitOrder(db, futApi, order, num)
|
||||
case 2: // 止损
|
||||
processFutStopLossOrder(db, order, price, num)
|
||||
case 4: //减仓
|
||||
processFutReduceOrder(order, price, num)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// 减仓单
|
||||
@ -506,16 +710,17 @@ func processFutTakeProfitOrder(db *gorm.DB, futApi FutRestApi, order models.Line
|
||||
if err != nil {
|
||||
logger.Error("合约止盈下单失败:", order.OrderSn, " err:", err)
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ?", order.Id).
|
||||
Updates(map[string]interface{}{"status": "2", "desc": err.Error(), "num": params.Quantity}).Error; err != nil {
|
||||
Updates(map[string]interface{}{"status": "2", "desc": err.Error(), "num": params.Quantity, "rate": order.Rate, "price": order.Price}).Error; err != nil {
|
||||
logger.Error("合约止盈下单失败,更新状态失败:", order.OrderSn, " err:", err)
|
||||
}
|
||||
} else {
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? ", order.Id).Updates(map[string]interface{}{"trigger_time": time.Now()}).Error; err != nil {
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? ", order.Id).
|
||||
Updates(map[string]interface{}{"trigger_time": time.Now(), "rate": order.Rate, "num": num.String(), "price": order.Price}).Error; err != nil {
|
||||
logger.Error("更新合约止盈单触发事件 ordersn:", order.OrderSn)
|
||||
}
|
||||
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ? and status =0", order.Id).
|
||||
Updates(map[string]interface{}{"status": "1", "num": num.String()}).Error; err != nil {
|
||||
Updates(map[string]interface{}{"status": "1"}).Error; err != nil {
|
||||
logger.Error("合约止盈下单成功,更新状态失败:", order.OrderSn, " err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,3 +154,19 @@ func GetSymbolTriggerCount(db *gorm.DB, symbol string, apiId, symbolType int) (i
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
//获取已开仓的
|
||||
// func GetOpenedOrders(db *gorm.DB, apiId int, exchange, symbol, symbolType, side string) ([]models.LinePreOrder, error) {
|
||||
|
||||
// }
|
||||
|
||||
// 获取子订单止盈止损数量
|
||||
func GetChildTpOrder(db *gorm.DB, pid int) (int, error) {
|
||||
var count int64
|
||||
|
||||
if err := db.Model(&models.LinePreOrder{}).Where("pid =? AND order_type>0 and order_type <3 and status =0", pid).Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
@ -83,13 +83,6 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
|
||||
return
|
||||
}
|
||||
|
||||
//判断是否有已触发交易对
|
||||
count, _ := GetSymbolTriggerCount(db, v.Symbol, v.ApiId, 1)
|
||||
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
price, _ := decimal.NewFromString(v.Price)
|
||||
num, _ := decimal.NewFromString(preOrder.Num)
|
||||
params := OrderPlacementService{
|
||||
@ -315,8 +308,8 @@ func SpotReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, spotApi SpotRest
|
||||
return
|
||||
} else if ok {
|
||||
defer lock.Release()
|
||||
takeOrder := DbModels.LinePreOrder{}
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type =1", reduceOrder.Pid).Find(&takeOrder).Error; err != nil {
|
||||
takeOrders := make([]DbModels.LinePreOrder, 0)
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_type =1 AND status IN (1,5)", reduceOrder.MainId).Find(&takeOrders).Error; err != nil {
|
||||
log.Error("查询止盈单失败")
|
||||
return
|
||||
}
|
||||
@ -327,19 +320,21 @@ func SpotReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, spotApi SpotRest
|
||||
return
|
||||
}
|
||||
|
||||
apiInfo, _ := GetApiInfo(takeOrder.ApiId)
|
||||
apiInfo, _ := GetApiInfo(reduceOrder.ApiId)
|
||||
|
||||
if apiInfo.Id == 0 {
|
||||
log.Error("现货减仓 查询api用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
for _, takeOrder := range takeOrders {
|
||||
err := CancelOpenOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn)
|
||||
|
||||
if err != nil {
|
||||
log.Error("现货止盈撤单失败", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
price := reduceOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.ReducePremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit))
|
||||
|
||||
params := OrderPlacementService{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user