diff --git a/app/api/enterprise/api/account.go b/app/api/enterprise/api/account.go index c887745..140a942 100644 --- a/app/api/enterprise/api/account.go +++ b/app/api/enterprise/api/account.go @@ -14,7 +14,7 @@ type Account struct{} type ( accountLoginForm struct { Mode int `json:"mode" form:"mode" binding:"required"` - Account string `json:"account" form:"account"` + Account string `json:"account" form:"account" binding:"required"` Captcha string `json:"captcha" form:"captcha"` Password string `json:"password" form:"password"` } @@ -27,6 +27,7 @@ type ( } ) +// Login 登陆操作 func (a *Account) Login(c *gin.Context) { form := new(accountLoginForm) diff --git a/app/api/enterprise/api/order.go b/app/api/enterprise/api/order.go new file mode 100644 index 0000000..238be93 --- /dev/null +++ b/app/api/enterprise/api/order.go @@ -0,0 +1,39 @@ +package api + +import ( + "SciencesServer/app/api/enterprise/controller/order" + "SciencesServer/app/basic/api" + "SciencesServer/app/session" + "github.com/gin-gonic/gin" +) + +type Order struct{} + +func (*Order) Index(c *gin.Context) { + form := &struct { + OrderNo string `json:"order_no" form:"order_no"` + Status string `json:"status" form:"status"` + api.PageForm + }{} + if err := api.Bind(form)(c); err != nil { + api.APIFailure(err.(error))(c) + return + } + data, err := order.NewInstance()(api.GetSession()(c).(*session.Enterprise), api.GetTenantID()(c).(uint64)). + Index(form.OrderNo, form.Status, form.Page, form.PageSize) + api.APIResponse(err, data)(c) +} + +func (*Order) Cancel(c *gin.Context) { + form := &struct { + api.IDStringForm + Remark string `json:"remark" form:"remark"` + }{} + if err := api.Bind(form)(c); err != nil { + api.APIFailure(err.(error))(c) + return + } + err := order.NewInstance()(api.GetSession()(c).(*session.Enterprise), api.GetTenantID()(c).(uint64)). + Cancel(form.Convert(), form.Remark) + api.APIResponse(err)(c) +} diff --git a/app/api/enterprise/api/payment.go b/app/api/enterprise/api/payment.go new file mode 100644 index 0000000..778f64e --- /dev/null +++ b/app/api/enterprise/api/payment.go @@ -0,0 +1 @@ +package api diff --git a/app/api/enterprise/controller/account/login.go b/app/api/enterprise/controller/account/login.go index 1d4ea69..61831b6 100644 --- a/app/api/enterprise/controller/account/login.go +++ b/app/api/enterprise/controller/account/login.go @@ -47,7 +47,7 @@ var loginHandle = map[LoginMode]func(*LoginParams, uint64) (*InstanceLoginParams // loginForSmsCaptcha 短信验证码登陆 func loginForSmsCaptcha(params *LoginParams, tenantID uint64) (*InstanceLoginParams, error) { if !utils.ValidateMobile(params.Captcha.Mobile) { - return nil, errors.New("操作错误,手机号码格式异常") + return nil, errors.New("手机号码格式异常") } pass, err := handle.NewCaptcha().Validate(&handle.CaptchaSms{ Mobile: params.Captcha.Mobile, Captcha: params.Captcha.Captcha, @@ -55,14 +55,14 @@ func loginForSmsCaptcha(params *LoginParams, tenantID uint64) (*InstanceLoginPar if err != nil { return nil, err } else if !pass { - return nil, errors.New("操作错误,验证码错误或已过期") + return nil, errors.New("验证码错误或已过期") } var isExist bool // 查询账号信息 mUserInstance := model.NewUserInstance() if isExist, err = model2.FirstField(mUserInstance.UserInstance, []string{"id", "uuid", "avatar", "name", "mobile", - "identity", "is_vip", "vip_deadline", "status"}, + "identity", "vip", "vip_deadline", "status"}, model2.NewWhere("mobile", params.Captcha.Mobile)); err != nil { return nil, err } @@ -75,7 +75,6 @@ func loginForSmsCaptcha(params *LoginParams, tenantID uint64) (*InstanceLoginPar if err = mUserIdentity.LastChooseInfo(mUserInstance.UUID); err != nil { return nil, err } - if mUserAssets, err = model.NewUserAssets().Assets(mUserInstance.UUID); err != nil { return nil, err } @@ -113,7 +112,7 @@ func loginForPassword(params *LoginParams, tenantID uint64) (*InstanceLoginParam mUserInstance := model.NewUserInstance() isExist, err := model2.FirstField(mUserInstance.UserInstance, []string{"id", "uuid", "name", "avatar", "mobile", - "identity", "is_vip", "vip_deadline", "password", "salt", "status"}, + "identity", "vip", "vip_deadline", "password", "salt", "status"}, model2.NewWhere("mobile", params.Password.Account)) if err != nil { diff --git a/app/api/enterprise/controller/account/register.go b/app/api/enterprise/controller/account/register.go index c518f0e..96baa66 100644 --- a/app/api/enterprise/controller/account/register.go +++ b/app/api/enterprise/controller/account/register.go @@ -1,7 +1,7 @@ package account import ( - model3 "SciencesServer/app/api/enterprise/model" + "SciencesServer/app/api/enterprise/model" model2 "SciencesServer/app/common/model" "SciencesServer/app/handle" "SciencesServer/serve/orm" @@ -40,6 +40,9 @@ func (c *RegisterParams) checkUserExist(mUserInstance *model2.UserInstance, tena // Launch 发起注册 func (c *Register) Launch(params *RegisterParams) (*InstanceLoginReturn, error) { + if !utils.ValidateMobile(params.Mobile) { + return nil, errors.New("手机号码错误") + } // 验证密码 if !params.checkPassword() { return nil, errors.New("两次密码不一致") @@ -53,7 +56,7 @@ func (c *Register) Launch(params *RegisterParams) (*InstanceLoginReturn, error) return nil, errors.New("验证码错误或已过期") } // 验证账号信息 - mUserInstance := model3.NewUserInstance() + mUserInstance := model.NewUserInstance() if pass, err = params.checkUserExist(mUserInstance.UserInstance, c.tenantID); err != nil { return nil, err @@ -64,7 +67,6 @@ func (c *Register) Launch(params *RegisterParams) (*InstanceLoginReturn, error) params.Name = params.Mobile } mUserInstance.Source = model2.UserInstanceSourceForLocal - mUserInstance.Password = utils.GetRandomString(12) mUserInstance.Mobile = params.Mobile mUserInstance.Name = params.Name mUserInstance.Password = params.Password diff --git a/app/api/enterprise/controller/order/instance.go b/app/api/enterprise/controller/order/instance.go new file mode 100644 index 0000000..bfba874 --- /dev/null +++ b/app/api/enterprise/controller/order/instance.go @@ -0,0 +1,140 @@ +package order + +import ( + "SciencesServer/app/api/enterprise/model" + "SciencesServer/app/basic/controller" + model2 "SciencesServer/app/common/model" + "SciencesServer/app/session" + "SciencesServer/serve/orm" + "SciencesServer/utils" + "errors" + "gorm.io/gorm" + "time" +) + +// Instance 订单信息 +type Instance struct { + *session.Enterprise + tenantID uint64 +} + +type InstanceHandle func(session *session.Enterprise, tenantID uint64) *Instance + +// InstanceInfo 订单信息 +type InstanceInfo struct { + ID string `json:"id"` + *model2.OrderInstance +} + +// Index 首页信息 +func (c *Instance) Index(orderNo, status string, page, pageSize int) (*controller.ReturnPages, error) { + mOrderInstance := model.NewOrderInstance() + + out := make([]*model2.OrderInstance, 0) + + where := []*model2.ModelWhereOrder{ + &model2.ModelWhereOrder{ + Where: model2.NewWhere("uid", c.UID), + Order: model2.NewOrder("id", model2.OrderModeToDesc), + }} + + if orderNo != "" { + where = append(where, &model2.ModelWhereOrder{ + Where: model2.NewWhereLike("order_no", orderNo), + }) + } + // 因int默认0,所以用string传递参数 + if status != "" { + where = append(where, &model2.ModelWhereOrder{ + Where: model2.NewWhereLike("status", utils.StringToInt(status)), + }) + } + var count int64 + + if err := model2.Pages(mOrderInstance.OrderInstance, &out, page, pageSize, &count, where...); err != nil { + return nil, err + } + + list := make([]*InstanceInfo, 0) + + for _, v := range out { + list = append(list, &InstanceInfo{ + ID: v.GetEncodeID(), OrderInstance: v, + }) + } + return &controller.ReturnPages{Data: list, Count: count}, nil +} + +// Cancel 订单取消 +func (c *Instance) Cancel(id uint64, remark string) error { + mOrderInstance := model.NewOrderInstance() + mOrderInstance.ID = id + + isExist, err := model2.FirstField(mOrderInstance.OrderInstance, []string{"id", "uid", "status"}) + + if err != nil { + return err + } else if !isExist { + return errors.New("操作错误,订单信息不存在或已被删除") + } else if mOrderInstance.UID != c.UID { + return errors.New("操作错误,无权限操作") + } + if mOrderInstance.Status == model2.OrderInstanceStatusForInit { + return errors.New("操作错误,当前订单不允许取消") + } + return orm.GetDB().Transaction(func(tx *gorm.DB) error { + if err = model2.Updates(mOrderInstance.OrderInstance, map[string]interface{}{ + "status": model2.OrderInstanceStatusForCancel, "updated_at": time.Now(), + }, tx); err != nil { + return err + } + mOrderLog := model.NewOrderLog() + mOrderLog.UID = c.UID + mOrderLog.OrderID = id + mOrderLog.Remark = remark + return model2.Create(mOrderLog.OrderLog, tx) + }) +} + +// Pay 支付操作 +func (c *Instance) Pay(id uint64) (interface{}, error) { + mOrderInstance := model.NewOrderInstance() + mOrderInstance.ID = id + + isExist, err := model2.FirstField(mOrderInstance.OrderInstance, []string{"id", "uid", "status"}) + + if err != nil { + return nil, err + } else if !isExist { + return nil, errors.New("操作错误,订单信息不存在或已被删除") + } else if mOrderInstance.UID != c.UID { + return nil, errors.New("操作错误,无权限操作") + } + if mOrderInstance.Status == model2.OrderInstanceStatusForInit { + return nil, errors.New("操作错误,当前订单不允许支付") + } + if err = orm.GetDB().Transaction(func(tx *gorm.DB) error { + if err = model2.Updates(mOrderInstance.OrderInstance, map[string]interface{}{ + "status": model2.OrderInstanceStatusForCancel, "updated_at": time.Now(), + }, tx); err != nil { + return err + } + mOrderLog := model.NewOrderLog() + mOrderLog.UID = c.UID + mOrderLog.OrderID = id + mOrderLog.Remark = "用户发起支付" + return model2.Create(mOrderLog.OrderLog, tx) + }); err != nil { + return nil, err + } + return nil, nil +} + +func NewInstance() InstanceHandle { + return func(session *session.Enterprise, tenantID uint64) *Instance { + return &Instance{ + Enterprise: session, + tenantID: tenantID, + } + } +} diff --git a/app/api/enterprise/controller/technology/patent.go b/app/api/enterprise/controller/technology/patent.go index f834e8d..7ab790a 100644 --- a/app/api/enterprise/controller/technology/patent.go +++ b/app/api/enterprise/controller/technology/patent.go @@ -204,18 +204,16 @@ func (c *Patent) List(kind int, title, applyCode, openCode, ipcCode string, page // 查询当前用户对应的专家信息 mUserExpert := model.NewUserExpert() - isExist, err := model2.LastWhere(mUserExpert.UserExpert, []string{"id", "expert_id"}, - model2.NewWhere("uid", c.UID), - model2.NewWhere("invalid_status", model2.InvalidStatusForNot), - ) + expert, err := mUserExpert.ExpertBasic(c.UID) + if err != nil { return nil, err - } else if !isExist { - return nil, nil + } else if expert.UserExpertID <= 0 { + return &controller.ReturnPages{}, nil } mTechnologyPatentExpert := model.NewTechnologyPatentExpert() - where := []*model2.ModelWhere{model2.NewWhere("u.expert_id", mUserExpert.ExpertID)} + where := []*model2.ModelWhere{model2.NewWhereFindInSet("p.inventor", expert.Name)} if kind <= 0 { where = append(where, model2.NewWhere("p.kind", kind)) diff --git a/app/api/enterprise/model/order_instance.go b/app/api/enterprise/model/order_instance.go new file mode 100644 index 0000000..25297e4 --- /dev/null +++ b/app/api/enterprise/model/order_instance.go @@ -0,0 +1,11 @@ +package model + +import "SciencesServer/app/common/model" + +type OrderInstance struct { + *model.OrderInstance +} + +func NewOrderInstance() *OrderInstance { + return &OrderInstance{model.NewOrderInstance()} +} diff --git a/app/api/enterprise/model/order_log.go b/app/api/enterprise/model/order_log.go new file mode 100644 index 0000000..54eac48 --- /dev/null +++ b/app/api/enterprise/model/order_log.go @@ -0,0 +1,11 @@ +package model + +import "SciencesServer/app/common/model" + +type OrderLog struct { + *model.OrderLog +} + +func NewOrderLog() *OrderLog { + return &OrderLog{model.NewOrderLog()} +} diff --git a/app/api/enterprise/model/user_expert.go b/app/api/enterprise/model/user_expert.go index 43165a6..b8cfde5 100644 --- a/app/api/enterprise/model/user_expert.go +++ b/app/api/enterprise/model/user_expert.go @@ -39,11 +39,26 @@ func (m *UserExpert) Expert(uid uint64) (*UserExpertInfo, error) { Select("u.id AS user_expert_id", "c.*"). Joins(fmt.Sprintf("LEFT JOIN %s AS c ON u.expert_id = c.id", model.NewManageExpert().TableName())). Where("u.uid = ?", uid). + Order("u.id "+model.OrderModeToDesc). Where("u.is_deleted = ? AND u.invalid_status = ?", model.DeleteStatusForNot, model.InvalidStatusForNot). Scan(out).Error return out, err } +// ExpertBasic 专家信息 +func (m *UserExpert) ExpertBasic(uid uint64) (*UserExpertInfo, error) { + out := new(UserExpertInfo) + + err := orm.GetDB().Table(m.TableName()+" AS u"). + Select("u.id AS user_expert_id", "c.name", "c.mobile"). + Joins(fmt.Sprintf("LEFT JOIN %s AS c ON u.expert_id = c.id", model.NewManageExpert().TableName())). + Where("u.uid = ?", uid). + Where("u.is_deleted = ? AND u.invalid_status = ?", model.DeleteStatusForNot, model.InvalidStatusForNot). + Order("u.id " + model.OrderModeToDesc). + Scan(out).Error + return out, err +} + func NewUserExpert() *UserExpert { return &UserExpert{model.NewUserExpert()} } diff --git a/app/common/migrate/instance.go b/app/common/migrate/instance.go index 0a5dbb8..4b3757c 100644 --- a/app/common/migrate/instance.go +++ b/app/common/migrate/instance.go @@ -145,6 +145,8 @@ func (this *Instance) Handle() { // 活动管理 &synchronized{iModel: model.NewActivityInstance()}, &synchronized{iModel: model.NewActivityApply()}, &synchronized{iModel: model.NewActivityApplyLog()}, &synchronized{iModel: model.NewActivityJoin()}, + // 订单管理 + &synchronized{iModel: model.NewOrderInstance()}, &synchronized{iModel: model.NewOrderLog()}, ) fmt.Printf("========================\n=== 数据完成迁移,成功【%d】,失败【%d】 ===\n========================\n", successCount, failureCount) diff --git a/app/common/model/order_instance.go b/app/common/model/order_instance.go new file mode 100644 index 0000000..710ca2e --- /dev/null +++ b/app/common/model/order_instance.go @@ -0,0 +1,75 @@ +package model + +import "encoding/json" + +// OrderInstance 订单数据模型 +type OrderInstance struct { + Model + ModelTenant + UID uint64 `gorm:"column:uid;type:int;default:0;comment:用户uuid" json:"-"` + Channel string `gorm:"column:channel;type:varchar(30);default:'';comment:订单支付渠道" json:"channel"` + OrderNo string `gorm:"column:order_no;type:varchar(30);default:'';comment:订单号" json:"order_no"` + Amount float64 `gorm:"column:amount;type:decimal(10,2);default:0;comment:订单金额" json:"amount"` + Params string `gorm:"column:params;type:varchar(255);default:'';comment:订单参数" json:"-"` + Status OrderInstanceStatus `gorm:"column:status;type:tinyint(1);default:0;comment:订单状态" json:"status"` + Remark string `gorm:"column:remark;type:varchar(255);default:'';comment:订单备注" json:"remark"` + ModelDeleted + ModelAt +} + +// OrderInstanceParams 订单参数 +type OrderInstanceParams struct { + Kind OrderInstanceParamsKind `json:"kind"` + Data interface{} `json:"data"` +} + +// OrderInstanceParamsKind 订单参数类型信息 +type OrderInstanceParamsKind int + +const ( + // OrderInstanceParamsKindForActivity 活动信息 + OrderInstanceParamsKindForActivity OrderInstanceParamsKind = iota + 1e2 + 1 +) + +// OrderInstanceParamsForActivity 订单活动参数 +type OrderInstanceParamsForActivity struct { + ID uint64 `json:"id"` +} + +// OrderInstanceStatus 订单状态 +type OrderInstanceStatus int + +const ( + // OrderInstanceStatusForInvalid 失效-未在规定时间内支付 + OrderInstanceStatusForInvalid OrderInstanceStatus = iota - 9 + // OrderInstanceStatusForCancel 取消-用户主动取消订单 + OrderInstanceStatusForCancel OrderInstanceStatus = iota - 2 + // OrderInstanceStatusForInit 初始化-初始化订单,待支付 + OrderInstanceStatusForInit + // OrderInstanceStatusForPaid 已支付 + OrderInstanceStatusForPaid + // OrderInstanceStatusForComplete 完成 + OrderInstanceStatusForComplete +) + +func (m *OrderInstance) TableName() string { + return "order_instance" +} + +func (m *OrderInstance) SetParamsAttribute(kind OrderInstanceParamsKind, data interface{}) { + value := &OrderInstanceParams{Kind: kind, Data: data} + _bytes, _ := json.Marshal(value) + m.Params = string(_bytes) +} + +func (m *OrderInstance) GetParamsAttribute() *OrderInstanceParams { + out := new(OrderInstanceParams) + + _ = json.Unmarshal([]byte(m.Params), out) + + return out +} + +func NewOrderInstance() *OrderInstance { + return &OrderInstance{} +} diff --git a/app/common/model/order_log.go b/app/common/model/order_log.go new file mode 100644 index 0000000..5269c42 --- /dev/null +++ b/app/common/model/order_log.go @@ -0,0 +1,19 @@ +package model + +// OrderLog 订单日志信息模型 +type OrderLog struct { + Model + UID uint64 `gorm:"column:uid;type:int;default:0;comment:用户uuid" json:"-"` + OrderID uint64 `gorm:"column:uid;type:int(11);default:0;comment:订单ID" json:"-"` + Remark string `gorm:"column:remark;type:varchar(255);default:'';comment:备注" json:"remark"` + ModelDeleted + ModelAt +} + +func (m *OrderLog) TableName() string { + return "order_log" +} + +func NewOrderLog() *OrderLog { + return &OrderLog{} +} diff --git a/utils/string_test.go b/utils/string_test.go index 7a40d61..1b52f04 100644 --- a/utils/string_test.go +++ b/utils/string_test.go @@ -1,9 +1,9 @@ package utils import ( - "fmt" "strings" "testing" + "time" ) func TestToSnake(t *testing.T) { @@ -11,5 +11,39 @@ func TestToSnake(t *testing.T) { //t.Log(src) //ReverseSlice(src) //t.Log(src) - t.Log(fmt.Sprintf("SELECT * FROM sys_user WHERE id IN (%v)", strings.Join([]string{"1", "2", "3"}, ","))) + //t.Log(fmt.Sprintf("SELECT * FROM sys_user WHERE id IN (%v)", strings.Join([]string{"1", "2", "3"}, ","))) + t.Log(strings.TrimSpace("123 213")) +} + +type ( + A struct { + Kind int `json:"kind"` + Data interface{} `json:"data"` + } + B struct { + Amount float64 `json:"amount"` + } +) + +func TestName(t *testing.T) { + a := new(A) + a.Kind = 1 + a.Data = &B{Amount: 8.88} + + src := AnyToJSON(a) + t.Log(src) + + time.Sleep(2 * time.Second) + + _a := new(A) + + err := FromJSON(src, _a) + + if err != nil { + t.Log(err) + } + t.Log(AnyToJSON(_a)) + + t.Log(a.Data.(*B).Amount) + }