zhou.xiaoning 3 anos atrás
pai
commit
4d7bbdd89e

+ 15 - 0
.vscode/launch.json

@@ -0,0 +1,15 @@
+{
+    // 使用 IntelliSense 了解相关属性。 
+    // 悬停以查看现有属性的描述。
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Package",
+            "type": "go",
+            "request": "launch",
+            "mode": "auto",
+            "program": "${workspaceFolder}/"
+        }
+    ]
+}

+ 7 - 47
core/rabbitmq.go

@@ -10,27 +10,7 @@ import (
 	"go.uber.org/zap"
 )
 
-// MQPacket 与总线交互的数据体
-type MQPacket struct {
-	FunCode   uint32  // 功能码
-	SessionId uint32  // 数据包的sid
-	Data      *[]byte // 业务数据体
-}
-
-// SubscribeInfo 订阅信息结构
-type SubscribeInfo struct {
-	Topic     string
-	QueueName string
-}
-
-// SubInfos 订阅信息数组
-var SubInfos []SubscribeInfo
-
-// MsgProcesser 消息处理者接口定义
-type MsgProcesser interface {
-	Process(string, string, *[]byte)
-}
-
+// RabbitMQ 连接总线
 func RabbitMQ() *global.RabbitMQ {
 	url := global.M2A_CONFIG.Rabbitmq.Url
 	connection, err := amqp.Dial(url)
@@ -51,31 +31,8 @@ func RabbitMQ() *global.RabbitMQ {
 	}
 }
 
-// SubscribeTopic 订阅主题
-func SubscribeTopic(topic string) (err error) {
-	// 创建队列名称
-	queuename := fmt.Sprintf("mtp20_access_%s", topic)
-
-	// 申明队列
-	if _, err = global.M2A_RABBITMQ.Channel.QueueDeclare(queuename, true, false, false, true, nil); err != nil {
-		global.M2A_LOG.Error("rabbitmq declear queue failed, err:", zap.Error(err))
-		return
-	}
-
-	// 绑定队列
-	if err = global.M2A_RABBITMQ.Channel.QueueBind(queuename, topic, "entry", false, nil); err != nil {
-		global.M2A_LOG.Error("rabbitmq bind queue failed, err:", zap.Error(err))
-		return
-	}
-
-	// 添加订阅信息
-	SubInfos = append(SubInfos, SubscribeInfo{Topic: topic, QueueName: queuename})
-
-	return
-}
-
 // Publish 发送消息
-func Publish(topic string, msg *MQPacket) (err error) {
+func Publish(topic string, msg *global.MQPacket) (err error) {
 	if global.M2A_RABBITMQ == nil || global.M2A_RABBITMQ.Connection.IsClosed() {
 		err = errors.New("rabbitmq is not connected")
 		global.M2A_LOG.Error("rabbitmq publish failed, err:", zap.Error(err))
@@ -104,7 +61,10 @@ func Publish(topic string, msg *MQPacket) (err error) {
 }
 
 // Receive 接收消息
-func Receive(topic, queuename string, processer MsgProcesser) (err error) {
+func Receive(topic string, processer global.MsgProcesser) (err error) {
+	// 队列名称
+	queuename := fmt.Sprintf("mtp20_access_%s", topic)
+
 	if global.M2A_RABBITMQ == nil || global.M2A_RABBITMQ.Connection.IsClosed() {
 		err = errors.New("rabbitmq is not connected")
 		global.M2A_LOG.Error("rabbitmq receive failed, err:", zap.Error(err))
@@ -119,7 +79,7 @@ func Receive(topic, queuename string, processer MsgProcesser) (err error) {
 
 	go func() {
 		for msg := range msgList {
-			processer.Process(topic, queuename, &msg.Body)
+			processer.Process(&msg.Body)
 			msg.Ack(false)
 		}
 	}()

+ 0 - 0
core/oracle.go → core/xorm_oracle.go


+ 1 - 2
global/funcode.go

@@ -1,6 +1,5 @@
 package global
 
 var (
-	T2bBankSignReq = 589825 // 签约请求
-	T2bBankSignRsp = 589826 // 签约应答
+	THJPurchaseTradeNtf = 1441865 // 铁合金成交通知
 )

+ 4 - 0
global/global.go

@@ -14,4 +14,8 @@ var (
 	M2A_LOG      *zap.Logger
 	M2A_DB       *xorm.Engine
 	M2A_RABBITMQ *RabbitMQ
+
+	M2A_MSGPROCESSER map[string]MsgProcesser // 总线信息处理器,key - 主题
+
+	M2A_DONE chan bool
 )

+ 13 - 0
global/rabbitmq.go

@@ -2,7 +2,20 @@ package global
 
 import "github.com/streadway/amqp"
 
+// RabbitMQ 总线结构体
 type RabbitMQ struct {
 	Connection *amqp.Connection
 	Channel    *amqp.Channel
 }
+
+// MQPacket 与总线交互的数据体
+type MQPacket struct {
+	FunCode   uint32  // 功能码
+	SessionId uint32  // 数据包的sid
+	Data      *[]byte // 业务数据体
+}
+
+// MsgProcesser 消息处理者接口
+type MsgProcesser interface {
+	Process(msg *[]byte)
+}

+ 1 - 2
global/topic.go

@@ -1,6 +1,5 @@
 package global
 
 var (
-	TOPIC_REQ_BANK = "bank_req" // 银行请求
-	TOPIC_RSP_BANK = "bank_rsp" // 银行回应
+	TOPIC_THJ_NTF = "thj_ntf" // 铁合金服务通知
 )

+ 3 - 0
go.mod

@@ -4,11 +4,13 @@ go 1.18
 
 require (
 	github.com/fsnotify/fsnotify v1.6.0
+	github.com/golang/protobuf v1.5.2
 	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
 	github.com/mattn/go-oci8 v0.1.1
 	github.com/spf13/viper v1.13.0
 	github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
 	go.uber.org/zap v1.23.0
+	google.golang.org/protobuf v1.28.0
 	xorm.io/xorm v1.3.2
 )
 
@@ -23,6 +25,7 @@ require (
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/nguyenthenguyen/docx v0.0.0-20220721043308-1903da0ef37d // indirect
 	github.com/pelletier/go-toml v1.9.5 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.5 // indirect
 	github.com/pkg/errors v0.9.1 // indirect

+ 10 - 0
go.sum

@@ -161,6 +161,9 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@@ -177,6 +180,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -370,6 +374,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
 github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/nguyenthenguyen/docx v0.0.0-20220721043308-1903da0ef37d h1:VcuXKGe6o4MSs/ymxb0p6YDsMkFvUSeCND8lN5eaTFY=
+github.com/nguyenthenguyen/docx v0.0.0-20220721043308-1903da0ef37d/go.mod h1:BZyH8oba3hE/BTt2FfBDGPOHhXiKs9RFmUvvXRdzrhM=
 github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@@ -858,6 +864,10 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=

+ 18 - 0
main.go

@@ -3,6 +3,7 @@ package main
 import (
 	"mtp20_assisted/core"
 	"mtp20_assisted/global"
+	"mtp20_assisted/service"
 
 	"go.uber.org/zap"
 )
@@ -23,4 +24,21 @@ func main() {
 	} else {
 		return
 	}
+
+	// 连接RabbitMQ
+	global.M2A_RABBITMQ = core.RabbitMQ()
+	if global.M2A_RABBITMQ != nil {
+		defer global.M2A_RABBITMQ.Connection.Close()
+	} else {
+		return
+	}
+	// 开始向总线创建和绑定队列
+	service.StartRabbitMQSubscribe()
+	// 构建总线信息处理器
+	service.InitRabbitMQMsgPreccesser()
+	// 开始接收总线消息
+	service.StartRabbitMQReceive()
+
+	global.M2A_DONE = make(chan bool)
+	<-global.M2A_DONE
 }

+ 23 - 0
model/bank.go

@@ -0,0 +1,23 @@
+package model
+
+import (
+	"fmt"
+	"mtp20_assisted/global"
+)
+
+// GetByUserID 通过UserID获取信息
+func (t *Bankaccountsign) GetByUserID(userID uint64) (has bool, err error) {
+	sql := fmt.Sprintf(`
+	select 
+		t.*
+	from BANK_ACCOUNTSIGN t
+	where t.ACCOUNTCODE in 
+		(select to_char(a.accountid) from taaccount a where a.RELATEDUSERID = %v)
+	`, userID)
+	return global.M2A_DB.SQL(sql).Get(t)
+}
+
+// Get 通过银行ID获取信息
+func (t *Bankbankinfo) Get() (has bool, err error) {
+	return global.M2A_DB.Where("BANKID = ?", t.BANKID).Get(t)
+}

+ 16 - 0
model/common.go

@@ -0,0 +1,16 @@
+package model
+
+import (
+	"fmt"
+	"mtp20_assisted/global"
+)
+
+// GetTotalAddressByDistrictID 通过地区ID获取完整地址
+func (t *Division) GetTotalAddressByDistrictID(address string) (totalAddress string, err error) {
+	has, err := global.M2A_DB.Where("AUTOID = ?", t.AUTOID).Get(t)
+	if err == nil && has {
+		totalAddress = fmt.Sprintf("%v%v", t.PATHNAME, address)
+	}
+
+	return
+}

+ 336 - 0
model/database.go

@@ -0,0 +1,336 @@
+package model
+
+import "time"
+
+// Thjpurchasetradedetail 铁合金采购成交扩展表
+type Thjpurchasetradedetail struct {
+	WRTRADEDETAILID      int64     `json:"wrtradedetailid" xorm:"WRTRADEDETAILID"`           // 采购成交单ID(321+Unix秒时间戳(10位)+xxxxxx)
+	PRESALEAPPLYID       int64     `json:"presaleapplyid" xorm:"PRESALEAPPLYID"`             // 预售申请ID(184+Unix秒时间戳(10位)+xxxxxx)
+	TRADEDATE            string    `json:"tradedate" xorm:"TRADEDATE"`                       // 交易日(yyyyMMdd)
+	MARKETID             int32     `json:"marketid" xorm:"MARKETID"`                         // 市场ID
+	WRFACTORTYPEID       int64     `json:"wrfactortypeid" xorm:"WRFACTORTYPEID"`             // 仓单要素类型ID
+	DELIVERYGOODSID      int32     `json:"deliverygoodsid" xorm:"DELIVERYGOODSID"`           // 现货品种ID
+	WRSTANDARDID         int32     `json:"wrstandardid" xorm:"WRSTANDARDID"`                 // 现货商品ID
+	WAREHOUSEID          int64     `json:"warehouseid" xorm:"WAREHOUSEID"`                   // 仓库ID
+	BUYUSERID            int64     `json:"buyuserid" xorm:"BUYUSERID"`                       // 买方用户ID
+	BUYACCOUNTID         int64     `json:"buyaccountid" xorm:"BUYACCOUNTID"`                 // 买方账号ID
+	SELLUSERID           int64     `json:"selluserid" xorm:"SELLUSERID"`                     // 卖方用户ID
+	SELLACCOUNTID        int64     `json:"sellaccountid" xorm:"SELLACCOUNTID"`               // 卖方账号ID
+	TRADETIME            time.Time `json:"tradetime" xorm:"TRADETIME"`                       // 摘牌时间
+	TRADEPRICE           float64   `json:"tradeprice" xorm:"TRADEPRICE"`                     // 摘牌价格
+	TRADEQTY             int64     `json:"tradeqty" xorm:"TRADEQTY"`                         // 摘牌数量
+	TRADEAMOUNT          float64   `json:"tradeamount" xorm:"TRADEAMOUNT"`                   // 摘牌总货款
+	DEPOSITRATE          float64   `json:"depositrate" xorm:"DEPOSITRATE"`                   // 定金比例
+	DISCOUNTAMOUNT       float64   `json:"discountamount" xorm:"DISCOUNTAMOUNT"`             // 优惠总金额(优惠金额*TradeQty)
+	PAYEDDEPOSIT         float64   `json:"payeddeposit" xorm:"PAYEDDEPOSIT"`                 // 买方已付定金
+	THJDELIVERYMODE      int32     `json:"thjdeliverymode" xorm:"THJDELIVERYMODE"`           // 交割方式 - 1:平台仓储 2:自提 3:代办运输 (枚举:THJDeliveryMode)
+	CONTACTNAME          string    `json:"contactname" xorm:"CONTACTNAME"`                   // 联系人姓名
+	CONTACTINFO          string    `json:"contactinfo" xorm:"CONTACTINFO"`                   // 联系方式
+	DESADDRESS           string    `json:"desaddress" xorm:"DESADDRESS"`                     // 目的地地址
+	RECEIPTINFO          string    `json:"receiptinfo" xorm:"RECEIPTINFO"`                   // 发票信息
+	ORDERSTATUS          int32     `json:"orderstatus" xorm:"ORDERSTATUS"`                   // 单据状态 - 1:待付尾款 2:支付尾款成功 3:支付尾款失败 4:已违约 5:卖方已确认 6:买方已确认 7:系统自动确认 (枚举:THJOrderStatus)
+	LASTPRICE            float64   `json:"lastprice" xorm:"LASTPRICE"`                       // 到期价格
+	LASTAMOUNT           float64   `json:"lastamount" xorm:"LASTAMOUNT"`                     // 到期总货款 = 到期价格 * 摘牌数量
+	BUYCHARGEVALUE       float64   `json:"buychargevalue" xorm:"BUYCHARGEVALUE"`             // 买方到期手续费
+	SELLCHARGEVALUE      float64   `json:"sellchargevalue" xorm:"SELLCHARGEVALUE"`           // 卖方到期手续费
+	REMAINAMOUNT         float64   `json:"remainamount" xorm:"REMAINAMOUNT"`                 // 剩余货款 = 到期总货款 - 已付定金 - 优惠金额
+	SELLCONFIRMREMARK    string    `json:"sellconfirmremark" xorm:"SELLCONFIRMREMARK"`       // 卖方确认备注
+	SELLCONFIRMATTACH    string    `json:"sellconfirmattach" xorm:"SELLCONFIRMATTACH"`       // 卖方确认附件
+	SELLCONFIRMTIME      time.Time `json:"sellconfirmtime" xorm:"SELLCONFIRMTIME"`           // 卖方确认时间
+	SELLCONFIRMTRADEDATE string    `json:"sellconfirmtradedate" xorm:"SELLCONFIRMTRADEDATE"` // 卖方确认交易日
+	BUYCONFIRMREMARK     string    `json:"buyconfirmremark" xorm:"BUYCONFIRMREMARK"`         // 买方确认备注
+	BUYCONFIRMTIME       time.Time `json:"buyconfirmtime" xorm:"BUYCONFIRMTIME"`             // 买方确认时间
+	HANDLESTATUS         int32     `json:"handlestatus" xorm:"HANDLESTATUS"`                 // 处理状态
+	CONTRACTADDRBUY      string    `json:"contractaddrbuy" xorm:"CONTRACTADDRBUY"`           // 贸易合同地址(买家)
+	CONTRACTADDRSELL     string    `json:"contractaddrsell" xorm:"CONTRACTADDRSELL"`         // 贸易合同地址(卖家)
+	PAYEDTRADEDATE       string    `json:"payedtradedate" xorm:"PAYEDTRADEDATE"`             // 支付尾款成功交易日
+}
+
+// TableName is THJ_PURCHASETRADEDETAIL
+func (r *Thjpurchasetradedetail) TableName() string {
+	return "THJ_PURCHASETRADEDETAIL"
+}
+
+// Userinfo 用户信息表
+type Userinfo struct {
+	USERID                   int64     `json:"userid" xorm:"USERID"`                                     // 用户ID
+	USERINFOTYPE             int32     `json:"userinfotype" xorm:"USERINFOTYPE"`                         // 用户信息类型 - 1:个人  2:企业
+	CUSTOMERNAME             string    `json:"customername" xorm:"CUSTOMERNAME"`                         // 客户名称(企业名称)
+	USERSTATUS               int32     `json:"userstatus" xorm:"USERSTATUS"`                             // 用户状态 - 1:正常 2:注销 3:停用
+	USERTYPE                 int32     `json:"usertype" xorm:"USERTYPE"`                                 // 账户类型 -  1:交易所 2:机构 3:会员子机构 4:经纪人 5:投资者 6:客户 7:企业成员(云平台)
+	OPENMODE                 int32     `json:"openmode" xorm:"OPENMODE"`                                 // 开户方式 -  1:管理端开户 2:网上开户注册(会员官网) 3:微信开户 4:网页交易端注册 5:安卓手机端注册 6:苹果手机端注册 7:PC交易端注册 8:微信快速开户 9:支付宝快速开户 10:手机号快速开户
+	CARDTYPEID               int32     `json:"cardtypeid" xorm:"CARDTYPEID"`                             // 证件类型ID
+	CARDNUM                  string    `json:"cardnum" xorm:"CARDNUM"`                                   // 证件号码(加密存储)
+	HALFBODYPHOTOURL         string    `json:"halfbodyphotourl" xorm:"HALFBODYPHOTOURL"`                 // 半身照地址
+	CARDFRONTPHOTOURL        string    `json:"cardfrontphotourl" xorm:"CARDFRONTPHOTOURL"`               // 证件正面图片地址
+	CARDBACKPHOTOURL         string    `json:"cardbackphotourl" xorm:"CARDBACKPHOTOURL"`                 // 证件背面图片地址
+	BIZNATURE                int32     `json:"biznature" xorm:"BIZNATURE"`                               // 企业性质( 企业) - 1:国有控股企业 2:集体控股企业 3:私人控股企业 4:港澳台商控股企业 5:外商控股企业 6:其它
+	BIZSCOPE                 string    `json:"bizscope" xorm:"BIZSCOPE"`                                 // 企业经营范围(企业)
+	LEGALPERSONNAME          string    `json:"legalpersonname" xorm:"LEGALPERSONNAME"`                   // 法人姓名(企业)
+	CONTACTNAME              string    `json:"contactname" xorm:"CONTACTNAME"`                           // 联系人
+	SEX                      int32     `json:"sex" xorm:"SEX"`                                           // 用户性别  0: 女  1: 男
+	TELPHONE                 string    `json:"telphone" xorm:"TELPHONE"`                                 // 联系电话(加密存储)
+	MOBILE                   string    `json:"mobile" xorm:"MOBILE"`                                     // 手机号码(加密存储)
+	FAX                      string    `json:"fax" xorm:"FAX"`                                           // 传真(加密存储)
+	EMAIL                    string    `json:"email" xorm:"EMAIL"`                                       // 邮件(加密存储)
+	QQ                       string    `json:"qq" xorm:"QQ"`                                             // QQ(加密存储
+	WECHAT                   string    `json:"wechat" xorm:"WECHAT"`                                     // 微信(加密存储)
+	COUNTRYID                int32     `json:"countryid" xorm:"COUNTRYID"`                               // 国家
+	PROVINCEID               int32     `json:"provinceid" xorm:"PROVINCEID"`                             // 省
+	CITYID                   int32     `json:"cityid" xorm:"CITYID"`                                     // 市
+	DISTRICTID               int32     `json:"districtid" xorm:"DISTRICTID"`                             // 地区
+	COMPANY                  string    `json:"company" xorm:"COMPANY"`                                   // 公司(个人)
+	ADDRESS                  string    `json:"address" xorm:"ADDRESS"`                                   // 地址
+	POSTALCODE               string    `json:"postalcode" xorm:"POSTALCODE"`                             // 邮政编码
+	CREATETIME               time.Time `json:"createtime" xorm:"CREATETIME"`                             // 创建时间
+	CREATORID                int64     `json:"creatorid" xorm:"CREATORID"`                               // 创建人
+	MODIFIERTIME             time.Time `json:"modifiertime" xorm:"MODIFIERTIME"`                         // 修改时间
+	MODIFIERID               int64     `json:"modifierid" xorm:"MODIFIERID"`                             // 修改人
+	REMARK                   string    `json:"remark" xorm:"REMARK"`                                     // 备注
+	WSKHINFO                 string    `json:"wskhinfo" xorm:"WSKHINFO"`                                 // 开户申请信息(JSON)
+	SIGNPDFURL               string    `json:"signpdfurl" xorm:"SIGNPDFURL"`                             // 签约pdf文件
+	LEGALCARDFRONTPHOTOURL   string    `json:"legalcardfrontphotourl" xorm:"LEGALCARDFRONTPHOTOURL"`     // 法人身份证正面照地址
+	LEGALCARDBACKPHOTOURL    string    `json:"legalcardbackphotourl" xorm:"LEGALCARDBACKPHOTOURL"`       // 法人身份证背面照地址
+	OTHERURL                 string    `json:"otherurl" xorm:"OTHERURL"`                                 // 其它图片地址[使用分号分隔]
+	HASENCRYPT               int32     `json:"hasencrypt" xorm:"HASENCRYPT"`                             // 数据是否已加密 - 0:未加密 1:已加密
+	BANKNAME                 string    `json:"bankname" xorm:"BANKNAME"`                                 // 银行名称
+	BANKACCOUNT              string    `json:"bankaccount" xorm:"BANKACCOUNT"`                           // 银行帐号 (加密存储)
+	BANKCARDFRONTPHOTOURL    string    `json:"bankcardfrontphotourl" xorm:"BANKCARDFRONTPHOTOURL"`       // 银行卡正面照地址
+	NEEDINVOICE              int32     `json:"needinvoice" xorm:"NEEDINVOICE"`                           // 是否需要发票 - 0:不需要 1:需要
+	BANKID                   string    `json:"bankid" xorm:"BANKID"`                                     // 银行编码
+	ATTACHMENT1              string    `json:"attachment1" xorm:"ATTACHMENT1"`                           // 附件1
+	ATTACHMENT2              string    `json:"attachment2" xorm:"ATTACHMENT2"`                           // 附件2
+	BANKACCOUNTNAME          string    `json:"bankaccountname" xorm:"BANKACCOUNTNAME"`                   // 收款人名称
+	HEADURL                  string    `json:"headurl" xorm:"HEADURL"`                                   // 头像地址
+	NICKNAME                 string    `json:"nickname" xorm:"NICKNAME"`                                 // 昵称:默认为名称脱敏(张**) 或 手机号脱敏(139****9999)
+	MOBILE2                  string    `json:"mobile2" xorm:"MOBILE2"`                                   // 手机号码[明文-尚志]
+	BIZTYPE                  int32     `json:"biztype" xorm:"BIZTYPE"`                                   // 企业类型 - 1:进口/生产 2:销售 3:零售 4:运输 5:仓储
+	PROXYSTATEMENTURL        string    `json:"proxystatementurl" xorm:"PROXYSTATEMENTURL"`               // 授权委托书
+	CONTACTCARDFRONTPHOTOURL string    `json:"contactcardfrontphotourl" xorm:"CONTACTCARDFRONTPHOTOURL"` // 联系人证件正面图片地址
+	CONTACTCARDBACKPHOTOURL  string    `json:"contactcardbackphotourl" xorm:"CONTACTCARDBACKPHOTOURL"`   // 联系人证件背面图片地址
+	ATTACHMENT3              string    `json:"attachment3" xorm:"ATTACHMENT3"`                           // 附件3
+	ATTACHMENT4              string    `json:"attachment4" xorm:"ATTACHMENT4"`                           // 附件4
+	ATTACHMENT5              string    `json:"attachment5" xorm:"ATTACHMENT5"`                           // 附件5
+	TAXPAYERNUM              string    `json:"taxpayernum" xorm:"TAXPAYERNUM"`                           // 纳税人识别号
+	BIRTHDAY                 time.Time `json:"birthday" xorm:"BIRTHDAY"`                                 // 生日(个人:年月日)
+	MODIFYSRC                int32     `json:"modifysrc" xorm:"MODIFYSRC"`                               // 修改来源 - 1:管理端 2:终端
+	LOGINCODE                string    `json:"logincode" xorm:"LOGINCODE"`                               // 登录代码
+}
+
+// TableName is USERINFO
+func (r *Userinfo) TableName() string {
+	return "USERINFO"
+}
+
+// Wrpresaleinfo 仓单预售信息表
+type Wrpresaleinfo struct {
+	PRESALEAPPLYID     int64     `json:"presaleapplyid" xorm:"PRESALEAPPLYID"`         // 预售申请ID(184+Unix秒时间戳(10位)+xxxxxx)
+	SELLUSERID         int64     `json:"selluserid" xorm:"SELLUSERID"`                 // 发行方用户ID
+	SELLACCOUNTID      int64     `json:"sellaccountid" xorm:"SELLACCOUNTID"`           // 发行方资金账户ID
+	DELIVERYGOODSID    int32     `json:"deliverygoodsid" xorm:"DELIVERYGOODSID"`       // 现货品种ID
+	WAREHOUSEID        int64     `json:"warehouseid" xorm:"WAREHOUSEID"`               // 仓库ID
+	WRSTANDARDID       int64     `json:"wrstandardid" xorm:"WRSTANDARDID"`             // 现货商品ID
+	WRFACTORTYPEID     int64     `json:"wrfactortypeid" xorm:"WRFACTORTYPEID"`         // 仓单要素类型ID - 根据现货商品\仓库生成
+	WRSTANDARDNAME     string    `json:"wrstandardname" xorm:"WRSTANDARDNAME"`         // 现货商品名称
+	UNITID             int32     `json:"unitid" xorm:"UNITID"`                         // 单位ID
+	UNITPRICE          float64   `json:"unitprice" xorm:"UNITPRICE"`                   // 商品单价
+	PRESALEQTY         int64     `json:"presaleqty" xorm:"PRESALEQTY"`                 // 预售总量
+	BASEQTY            int64     `json:"baseqty" xorm:"BASEQTY"`                       // 中签基数
+	MAXBUYQTY          int64     `json:"maxbuyqty" xorm:"MAXBUYQTY"`                   // 单人最大申购量
+	MAXLUCKYQTY        int64     `json:"maxluckyqty" xorm:"MAXLUCKYQTY"`               // 单人最大中签量 - 作废
+	STARTDATE          time.Time `json:"startdate" xorm:"STARTDATE"`                   // 预售开始日期
+	ENDDATE            time.Time `json:"enddate" xorm:"ENDDATE"`                       // 预售结束日期
+	TAKESTARTDATE      time.Time `json:"takestartdate" xorm:"TAKESTARTDATE"`           // 提货开始日期
+	THUMURLS           string    `json:"thumurls" xorm:"THUMURLS"`                     // 缩略图片(1:1)(逗号分隔)
+	PICTUREURLS        string    `json:"pictureurls" xorm:"PICTUREURLS"`               // 详情图片(逗号分隔)
+	BANNERPICURL       string    `json:"bannerpicurl" xorm:"BANNERPICURL"`             // Banner图(逗号分隔)
+	PRESALESTATUS      int32     `json:"presalestatus" xorm:"PRESALESTATUS"`           // 预售状态 - 1:未开始 2:进行中 3:已结束 4:已关闭 5:处理中 6::处理失败 7:已完成
+	LOTTERYFLAG        int32     `json:"lotteryflag" xorm:"LOTTERYFLAG"`               // 摇号标识 - 0:未摇号 1:已摇号 2:摇号中 3:摇号失败
+	LOTTERYQTY         int64     `json:"lotteryqty" xorm:"LOTTERYQTY"`                 // 摇号总量
+	LUCKYQTY           int64     `json:"luckyqty" xorm:"LUCKYQTY"`                     // 已中签量\成交量
+	PLACEQTY           int64     `json:"placeqty" xorm:"PLACEQTY"`                     // 已配售量
+	MARKETID           int32     `json:"marketid" xorm:"MARKETID"`                     // 市场ID
+	SELLWRTRADEORDERID int64     `json:"sellwrtradeorderid" xorm:"SELLWRTRADEORDERID"` // 发行方卖委托单ID
+	CREATETIME         time.Time `json:"createtime" xorm:"CREATETIME"`                 // 创建时间
+	TRADEDATE          string    `json:"tradedate" xorm:"TRADEDATE"`                   // 交易日
+	LUCKYNUMS          string    `json:"luckynums" xorm:"LUCKYNUMS"`                   // 中签号码(按顺序逗号分隔)
+	LASTPRICE          float64   `json:"lastprice" xorm:"LASTPRICE"`                   // 实际价格(64)
+	ENDHANDLETIME      time.Time `json:"endhandletime" xorm:"ENDHANDLETIME"`           // 到期处理时间
+}
+
+// TableName is WR_PRESALEINFO
+func (r *Wrpresaleinfo) TableName() string {
+	return "WR_PRESALEINFO"
+}
+
+// Bankaccountsign 账户签解约信息表
+type Bankaccountsign struct {
+	ACCOUNTCODE      string    `json:"accountcode" xorm:"ACCOUNTCODE"`           // 资金账号
+	CUSBANKID        string    `json:"cusbankid" xorm:"CUSBANKID"`               // 托管银行编号
+	SIGNSTATUS       int32     `json:"signstatus" xorm:"SIGNSTATUS"`             // 签约状态 - 1:未签约 2:签约待审核 3:签约中 4:已签约 5:解约待审核 6:解约中 7:已解约 8:已解绑 9:绑卡中 10:审核拒绝 11:换签待审核
+	CURRENCY         string    `json:"currency" xorm:"CURRENCY"`                 // 币种
+	ACCOUNTTYPE      int32     `json:"accounttype" xorm:"ACCOUNTTYPE"`           // 账户类型(UserType)
+	ACCOUNTNAME      string    `json:"accountname" xorm:"ACCOUNTNAME"`           // 资金账号对应的账号名(UserName)
+	BANKCARDTYPE     int32     `json:"bankcardtype" xorm:"BANKCARDTYPE"`         // 银行卡类型
+	BANKACCOUNTNO    string    `json:"bankaccountno" xorm:"BANKACCOUNTNO"`       // 银行卡号
+	BANKACCOUNTTYPE  int32     `json:"bankaccounttype" xorm:"BANKACCOUNTTYPE"`   // 银行账户类型 - 1-对私; 2-对公
+	BANKCHILDACCOUNT string    `json:"bankchildaccount" xorm:"BANKCHILDACCOUNT"` // 银行子账号(签约成功后,很多银行会返回对应的这个虚拟账号)
+	BANKID           string    `json:"bankid" xorm:"BANKID"`                     // 签约银行ID
+	BRANCHBANKID     string    `json:"branchbankid" xorm:"BRANCHBANKID"`         // 签约银行支行号
+	BRANCHBANKNAME   string    `json:"branchbankname" xorm:"BRANCHBANKNAME"`     // 签约银行支行名称
+	BANKACCOUNTNAME  string    `json:"bankaccountname" xorm:"BANKACCOUNTNAME"`   // 签约银行卡账号名
+	CARDTYPE         string    `json:"cardtype" xorm:"CARDTYPE"`                 // 证件类型
+	CARDNO           string    `json:"cardno" xorm:"CARDNO"`                     // 证件号码
+	BANKPROVINCE     string    `json:"bankprovince" xorm:"BANKPROVINCE"`         // 开户行省份
+	BANKCITY         string    `json:"bankcity" xorm:"BANKCITY"`                 // 开户行城市
+	DIRECT           int32     `json:"direct" xorm:"DIRECT"`                     // 方向(可以判断那方先发起的签约)
+	MOBILEPHONE      string    `json:"mobilephone" xorm:"MOBILEPHONE"`           // 手机号
+	EXTENDINFO       string    `json:"extendinfo" xorm:"EXTENDINFO"`             // 扩展信息(JSON字符串)
+	EXCHTICKET       string    `json:"exchticket" xorm:"EXCHTICKET"`             // 最后一次签约成功的流水号
+	UPDATETIME       time.Time `json:"updatetime" xorm:"UPDATETIME"`             // 更新时间(签解约更新时间)
+	APPLICATIONTIME  time.Time `json:"applicationtime" xorm:"APPLICATIONTIME"`   // 最后一次更新的时间
+	NETADDR          string    `json:"netaddr" xorm:"NETADDR"`                   // 调转网址
+	AUDITID          int64     `json:"auditid" xorm:"AUDITID"`                   // 审核人
+	AUDITTIME        time.Time `json:"audittime" xorm:"AUDITTIME"`               // 审核时间
+	APPLYEXCHTICKET  string    `json:"applyexchticket" xorm:"APPLYEXCHTICKET"`   // 申请流水
+}
+
+// TableName is BANK_ACCOUNTSIGN
+func (r *Bankaccountsign) TableName() string {
+	return "BANK_ACCOUNTSIGN"
+}
+
+// Taaccount 资金账户表 - 导历史
+type Taaccount struct {
+	ACCOUNTID             int64     `json:"accountid" xorm:"ACCOUNTID"`                         // 资金账户ID
+	USERID                int64     `json:"userid" xorm:"USERID"`                               // 用户ID
+	CURRENCYID            int64     `json:"currencyid" xorm:"CURRENCYID"`                       // 货币ID
+	CHANGEFLAG            int32     `json:"changeflag" xorm:"CHANGEFLAG"`                       // 变动标志(当前账户资金有任何变动更新为1系统结算时更新0;供清算时使用) 0:无变动 1:有变动
+	PASSWORD              string    `json:"password" xorm:"PASSWORD"`                           // 资金密码
+	TRADESTATUS           int32     `json:"tradestatus" xorm:"TRADESTATUS"`                     // 交易状态 - 1:正常 2:受限 3:冻结(停用) 4:禁止建仓(人工受限) 5:禁止交易(人工冻结) 6:待激活 7:已删除(注销)
+	SIGNSTATUS            int32     `json:"signstatus" xorm:"SIGNSTATUS"`                       // 签约状态 - 1:未签约 2:签约待审核 3:签约中 4:已签约 5:解约待审核 6:解约中 7:已解约 8:已解绑 9:绑卡中
+	ISMAIN                int32     `json:"ismain" xorm:"ISMAIN"`                               // 是否母账号 0:不是母账户 1:是母账户
+	PARENTACCOUNTID       int64     `json:"parentaccountid" xorm:"PARENTACCOUNTID"`             // 所属根账号
+	RELATEDUSERID         int64     `json:"relateduserid" xorm:"RELATEDUSERID"`                 // 关联用户
+	RELATEDACCOUNTSTATUS  int32     `json:"relatedaccountstatus" xorm:"RELATEDACCOUNTSTATUS"`   // 关联用户交易权限状态 - 1:正常(可交易) 2:受限(可平仓,不可建仓) 3:冻结(不可交易)
+	TAACCOUNTTYPE         int32     `json:"taaccounttype" xorm:"TAACCOUNTTYPE"`                 // 账号类型 - 1:外部账号 2:内部账号 3:内部做市自营账号 4:内部做市接单账号
+	ISRECKONACCOUNT       int32     `json:"isreckonaccount" xorm:"ISRECKONACCOUNT"`             // 是否机构分润账号 0:不是 1:是
+	ISMARKETACCOUNT       int32     `json:"ismarketaccount" xorm:"ISMARKETACCOUNT"`             // 是否机构接单账号 0:不是 1:是
+	BALANCE               float64   `json:"balance" xorm:"BALANCE"`                             // 期初余额
+	ORIFREEZEMARGIN       float64   `json:"orifreezemargin" xorm:"ORIFREEZEMARGIN"`             // 期初冻结保证金
+	ORIUSEDMARGIN         float64   `json:"oriusedmargin" xorm:"ORIUSEDMARGIN"`                 // 期初占用保证金
+	ORIOTHERFREEZEMARGIN  float64   `json:"oriotherfreezemargin" xorm:"ORIOTHERFREEZEMARGIN"`   // 期初其他冻结保证金(出金冻结资金 交割买方冻结 申购冻结 全款买入 商城买入)
+	ORIFREEZECHARGE       float64   `json:"orifreezecharge" xorm:"ORIFREEZECHARGE"`             // 期初手续费冻结
+	ORIMORTGAGECREDIT     float64   `json:"orimortgagecredit" xorm:"ORIMORTGAGECREDIT"`         // 期初授信金额
+	ORIOTHERCREDIT        float64   `json:"oriothercredit" xorm:"ORIOTHERCREDIT"`               // 期初其它授信金额
+	ORIOUTAMOUNTFREEZE    float64   `json:"orioutamountfreeze" xorm:"ORIOUTAMOUNTFREEZE"`       // 期初出金冻结
+	FREEZEMARGIN          float64   `json:"freezemargin" xorm:"FREEZEMARGIN"`                   // 冻结保证金
+	USEDMARGIN            float64   `json:"usedmargin" xorm:"USEDMARGIN"`                       // 占用保证金
+	OTHERFREEZEMARGIN     float64   `json:"otherfreezemargin" xorm:"OTHERFREEZEMARGIN"`         // 其他冻结保证金(交割买方冻结 申购冻结 全款买入 商城买入)
+	FREEZECHARGE          float64   `json:"freezecharge" xorm:"FREEZECHARGE"`                   // 手续费冻结
+	MORTGAGECREDIT        float64   `json:"mortgagecredit" xorm:"MORTGAGECREDIT"`               // 授信金额
+	OTHERCREDIT           float64   `json:"othercredit" xorm:"OTHERCREDIT"`                     // 其它授信金额
+	OUTAMOUNTFREEZE       float64   `json:"outamountfreeze" xorm:"OUTAMOUNTFREEZE"`             // 出金冻结
+	INAMOUNT              float64   `json:"inamount" xorm:"INAMOUNT"`                           // 今日入金金额(包括三方入金)
+	CURRENTBALANCE        float64   `json:"currentbalance" xorm:"CURRENTBALANCE"`               // 期末余额
+	OUTAMOUNT             float64   `json:"outamount" xorm:"OUTAMOUNT"`                         // 今日出金金额(包括三方出金)
+	PAYCHARGE             float64   `json:"paycharge" xorm:"PAYCHARGE"`                         // 今日手续费支出
+	CLOSEPL               float64   `json:"closepl" xorm:"CLOSEPL"`                             // 今日平仓盈亏
+	CREDITINCREASE        float64   `json:"creditincrease" xorm:"CREDITINCREASE"`               // 今日授信增加
+	CREDITDECREASE        float64   `json:"creditdecrease" xorm:"CREDITDECREASE"`               // 今日授信减少
+	OTHERCREDITINCREASE   float64   `json:"othercreditincrease" xorm:"OTHERCREDITINCREASE"`     // 今日其它授信增加
+	OTHERCREDITDECREASE   float64   `json:"othercreditdecrease" xorm:"OTHERCREDITDECREASE"`     // 今日其它授信减少
+	TRANSFERAMOUNT        float64   `json:"transferamount" xorm:"TRANSFERAMOUNT"`               // 今日划转金额(母子账号资金划转,从划入账号为正,从账号划出为负)
+	OTHERPAY              float64   `json:"otherpay" xorm:"OTHERPAY"`                           // 其他支出(交割付款 申购付款 全款买入 商城买入 卖家退货)
+	OTHERINCOME           float64   `json:"otherincome" xorm:"OTHERINCOME"`                     // 其他收入(交割收款 申购收款 全款卖出 商城卖出 买家退货 会员手续费收入)
+	OUTTHRESHOLD          float64   `json:"outthreshold" xorm:"OUTTHRESHOLD"`                   // 出金阈值
+	TRADESTATUSCHANGETIME time.Time `json:"tradestatuschangetime" xorm:"TRADESTATUSCHANGETIME"` // 激活时间
+	CHANGETIME            time.Time `json:"changetime" xorm:"CHANGETIME"`                       // 账户状态变更时间
+	THIRDINAMOUNT         float64   `json:"thirdinamount" xorm:"THIRDINAMOUNT"`                 // 今日三方入金
+	THIRDOUTAMOUNT        float64   `json:"thirdoutamount" xorm:"THIRDOUTAMOUNT"`               // 今日三方出金
+	CAPITALBALANCE        float64   `json:"capitalbalance" xorm:"CAPITALBALANCE"`               // 本金余额[外部子母账户实际出入金余额]
+	FROMACCOUNTID         int64     `json:"fromaccountid" xorm:"FROMACCOUNTID"`                 // 所属上级账户
+	SUBLEVELPATH          string    `json:"sublevelpath" xorm:"SUBLEVELPATH"`                   // 账号层级路径(逗号分隔,首尾加逗号)
+	SERIVCEGROUP          int64     `json:"serivcegroup" xorm:"SERIVCEGROUP"`                   // 服务分组
+	ACCOUNTNAME           string    `json:"accountname" xorm:"ACCOUNTNAME"`                     // 账户名称
+	ACCOUNTFLAG           int32     `json:"accountflag" xorm:"ACCOUNTFLAG"`                     // 账户标识 - 0\1 (默认为0, 当上级账户与本账户的关联用户均为自己时更新为1)
+	ORIDEBT               float64   `json:"oridebt" xorm:"ORIDEBT"`                             // 期初欠款
+	CURDEBT               float64   `json:"curdebt" xorm:"CURDEBT"`                             // 期末欠款
+	MODIFYTIME            time.Time `json:"modifytime" xorm:"MODIFYTIME"`                       // 修改时间
+	MODIFYSRC             int32     `json:"modifysrc" xorm:"MODIFYSRC"`                         // 修改来源 - 1:管理端 2:终端
+	MODIFIERID            int64     `json:"modifierid" xorm:"MODIFIERID"`                       // 修改人
+}
+
+// TableName is TAACCOUNT
+func (r *Taaccount) TableName() string {
+	return "TAACCOUNT"
+}
+
+// Division 行政区域表
+type Division struct {
+	AUTOID        int64     `json:"autoid" xorm:"AUTOID"`               // 自增ID
+	DIVISIONCODE  string    `json:"divisioncode" xorm:"DIVISIONCODE"`   // 行政代码
+	SHORTCODE     string    `json:"shortcode" xorm:"SHORTCODE"`         // 地区简码
+	PARENTCODE    string    `json:"parentcode" xorm:"PARENTCODE"`       // 上级行政代码
+	DIVISIONLEVEL string    `json:"divisionlevel" xorm:"DIVISIONLEVEL"` // 行政级别
+	DIVISIONNAME  string    `json:"divisionname" xorm:"DIVISIONNAME"`   // 行政名称
+	PATHNAME      string    `json:"pathname" xorm:"PATHNAME"`           // 路径名称
+	SEPARABLENAME string    `json:"separablename" xorm:"SEPARABLENAME"` // 可拆分的全称
+	POSTCODE      string    `json:"postcode" xorm:"POSTCODE"`           // 邮政编码
+	MODIFYTIME    time.Time `json:"modifytime" xorm:"MODIFYTIME"`       // 修改时间
+	MODIFIERID    int64     `json:"modifierid" xorm:"MODIFIERID"`       // 修改人
+}
+
+// TableName is DIVISION
+func (r *Division) TableName() string {
+	return "DIVISION"
+}
+
+// Bankbankinfo 银行信息表(清算中心Bank表)
+type Bankbankinfo struct {
+	BANKID      string `json:"bankid" xorm:"BANKID"`           // 银行ID
+	BANKNAME    string `json:"bankname" xorm:"BANKNAME"`       // 银行名称
+	CLEARBANKNO string `json:"clearbankno" xorm:"CLEARBANKNO"` // 清算系统银行编号
+	STATUS      int32  `json:"status" xorm:"STATUS"`           // 状态 - 0:正常 1:注销
+	ORDERINDEX  int64  `json:"orderindex" xorm:"ORDERINDEX"`   // 排序顺序
+}
+
+// TableName is BANK_BANKINFO
+func (r *Bankbankinfo) TableName() string {
+	return "BANK_BANKINFO"
+}
+
+// Wrstandard 现货商品表
+type Wrstandard struct {
+	WRSTANDARDID      int64     `json:"wrstandardid" xorm:"WRSTANDARDID"`           // 现货商品ID(自增 SEQ_GOODS 确保不重复)
+	WRSTANDARDCODE    string    `json:"wrstandardcode" xorm:"WRSTANDARDCODE"`       // 现货商品代码
+	WRSTANDARDNAME    string    `json:"wrstandardname" xorm:"WRSTANDARDNAME"`       // 现货商品名称
+	DELIVERYGOODSID   int32     `json:"deliverygoodsid" xorm:"DELIVERYGOODSID"`     // 现货品种ID
+	UNITID            int32     `json:"unitid" xorm:"UNITID"`                       // 现货商品单位ID
+	MINIVALUE         int64     `json:"minivalue" xorm:"MINIVALUE"`                 // 最小变动值
+	MINIVALUEDP       int64     `json:"minivaluedp" xorm:"MINIVALUEDP"`             // 最小变动值小数位
+	REALMINIVALUE     int64     `json:"realminivalue" xorm:"REALMINIVALUE"`         // 实际最小变动值
+	REALMINIVALUEDP   int64     `json:"realminivaluedp" xorm:"REALMINIVALUEDP"`     // 实际最小变动值小数位
+	WRSSTATUS         int32     `json:"wrsstatus" xorm:"WRSSTATUS"`                 // 状态 - 作废 - 0:未激活 1:正常
+	CREATORID         int64     `json:"creatorid" xorm:"CREATORID"`                 // 创建人
+	CREATETIME        time.Time `json:"createtime" xorm:"CREATETIME"`               // 创建时间
+	UPDATORID         int64     `json:"updatorid" xorm:"UPDATORID"`                 // 更新人
+	UPDATETIME        time.Time `json:"updatetime" xorm:"UPDATETIME"`               // 更新时间
+	FACTORYITEMJSON   string    `json:"factoryitemjson" xorm:"FACTORYITEMJSON"`     // 要素项定义Json[{"DGFactoryItemTypeID": ,"ItemTypeMode": ,"FactoryItemIDs": },{.....},]DGFactoryItemTypeID - 要素项类型ID --DGFactoryItem->DGFactoryItemTypeIDItemTypeMode - 要素项类型模式 --DGFactoryItem->ItemTypeModeFactoryItemIDs - 选择项IDs--DGFactoryItem->DGFactoryItemID, 逗号分隔
+	ISVALID           int32     `json:"isvalid" xorm:"ISVALID"`                     // 是否有效 - 0:无效 1:有效
+	AREAUSERID        int64     `json:"areauserid" xorm:"AREAUSERID"`               // 所属机构
+	REMARK            string    `json:"remark" xorm:"REMARK"`                       // 备注
+	CONVERTFACTOR     float64   `json:"convertfactor" xorm:"CONVERTFACTOR"`         // 标仓系数
+	VATRATE           float64   `json:"vatrate" xorm:"VATRATE"`                     // 现货增值税率
+	STORAGEFEE        float64   `json:"storagefee" xorm:"STORAGEFEE"`               // 仓储费(固定: 111)
+	THUMURLS          string    `json:"thumurls" xorm:"THUMURLS"`                   // 缩略图片(1:1)(逗号分隔)
+	PICTUREURLS       string    `json:"pictureurls" xorm:"PICTUREURLS"`             // 详情图片(逗号分隔)
+	BANNERPICURL      string    `json:"bannerpicurl" xorm:"BANNERPICURL"`           // Banner图(逗号分隔)
+	PROVIDERUSERID    int64     `json:"provideruserid" xorm:"PROVIDERUSERID"`       // 供应链提供商
+	PROVIDERACCOUNTID int64     `json:"provideraccountid" xorm:"PROVIDERACCOUNTID"` // 供应链提供商资金账户 ID
+}
+
+// TableName is WRSTANDARD
+func (r *Wrstandard) TableName() string {
+	return "WRSTANDARD"
+}

+ 13 - 0
model/thj.go

@@ -0,0 +1,13 @@
+package model
+
+import "mtp20_assisted/global"
+
+// Get 通过采购成交单ID获取信息
+func (t *Thjpurchasetradedetail) Get() (has bool, err error) {
+	return global.M2A_DB.Where("WRTRADEDETAILID = ?", t.WRTRADEDETAILID).Get(t)
+}
+
+// Get 通过预售申请ID获取信息
+func (t *Wrpresaleinfo) Get() (has bool, err error) {
+	return global.M2A_DB.Where("PRESALEAPPLYID = ?", t.PRESALEAPPLYID).Get(t)
+}

+ 10 - 0
model/user.go

@@ -0,0 +1,10 @@
+package model
+
+import (
+	"mtp20_assisted/global"
+)
+
+// Get 通过用户ID获取信息
+func (t *Userinfo) Get() (has bool, err error) {
+	return global.M2A_DB.Where("USERID = ?", t.USERID).Get(t)
+}

+ 8 - 0
model/wrstandard.go

@@ -0,0 +1,8 @@
+package model
+
+import "mtp20_assisted/global"
+
+// Get 通过现货商品ID获取信息
+func (t *Wrstandard) Get() (has bool, err error) {
+	return global.M2A_DB.Where("WRSTANDARDID = ?", t.WRSTANDARDID).Get(t)
+}

+ 2 - 0
res/pb/generate_go.bat

@@ -0,0 +1,2 @@
+protoc.exe --proto_path=./ -I=./ --go_out=./  *.proto
+pause

+ 321 - 0
res/pb/mtp2.pb.go

@@ -0,0 +1,321 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.25.0
+// 	protoc        v3.11.4
+// source: mtp2.proto
+
+package pb
+
+import (
+	proto "github.com/golang/protobuf/proto"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
+
+// 消息头
+type MessageHead struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	FunCode       *uint32 `protobuf:"varint,1,opt,name=FunCode" json:"FunCode,omitempty"`             // 功能号
+	RequestID     *uint32 `protobuf:"varint,2,opt,name=RequestID" json:"RequestID,omitempty"`         // 客户端的流水ID
+	AccountID     *uint64 `protobuf:"varint,3,opt,name=AccountID" json:"AccountID,omitempty"`         // 账号ID
+	AccessID      *uint32 `protobuf:"varint,4,opt,name=AccessID" json:"AccessID,omitempty"`           //二级分配给客户端的接入ID
+	ClientTime    *int64  `protobuf:"varint,5,opt,name=ClientTime" json:"ClientTime,omitempty"`       //消息发起时间
+	GoodsID       *uint32 `protobuf:"varint,6,opt,name=GoodsID" json:"GoodsID,omitempty"`             //商品ID
+	UUID          *string `protobuf:"bytes,7,opt,name=UUID" json:"UUID,omitempty"`                    // 消息唯一ID
+	MarketID      *uint32 `protobuf:"varint,8,opt,name=MarketID" json:"MarketID,omitempty"`           // 所属市场ID
+	UserID        *uint32 `protobuf:"varint,9,opt,name=UserID" json:"UserID,omitempty"`               // 用户ID
+	ResponseTopic *string `protobuf:"bytes,10,opt,name=ResponseTopic" json:"ResponseTopic,omitempty"` // 应答消息所属主题
+	AccountID2    *uint64 `protobuf:"varint,11,opt,name=AccountID2" json:"AccountID2,omitempty"`      // 账号ID-币币交易使用
+}
+
+func (x *MessageHead) Reset() {
+	*x = MessageHead{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_mtp2_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MessageHead) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageHead) ProtoMessage() {}
+
+func (x *MessageHead) ProtoReflect() protoreflect.Message {
+	mi := &file_mtp2_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageHead.ProtoReflect.Descriptor instead.
+func (*MessageHead) Descriptor() ([]byte, []int) {
+	return file_mtp2_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *MessageHead) GetFunCode() uint32 {
+	if x != nil && x.FunCode != nil {
+		return *x.FunCode
+	}
+	return 0
+}
+
+func (x *MessageHead) GetRequestID() uint32 {
+	if x != nil && x.RequestID != nil {
+		return *x.RequestID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetAccountID() uint64 {
+	if x != nil && x.AccountID != nil {
+		return *x.AccountID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetAccessID() uint32 {
+	if x != nil && x.AccessID != nil {
+		return *x.AccessID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetClientTime() int64 {
+	if x != nil && x.ClientTime != nil {
+		return *x.ClientTime
+	}
+	return 0
+}
+
+func (x *MessageHead) GetGoodsID() uint32 {
+	if x != nil && x.GoodsID != nil {
+		return *x.GoodsID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetUUID() string {
+	if x != nil && x.UUID != nil {
+		return *x.UUID
+	}
+	return ""
+}
+
+func (x *MessageHead) GetMarketID() uint32 {
+	if x != nil && x.MarketID != nil {
+		return *x.MarketID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetUserID() uint32 {
+	if x != nil && x.UserID != nil {
+		return *x.UserID
+	}
+	return 0
+}
+
+func (x *MessageHead) GetResponseTopic() string {
+	if x != nil && x.ResponseTopic != nil {
+		return *x.ResponseTopic
+	}
+	return ""
+}
+
+func (x *MessageHead) GetAccountID2() uint64 {
+	if x != nil && x.AccountID2 != nil {
+		return *x.AccountID2
+	}
+	return 0
+}
+
+// 铁合金成交通知
+type THJPurchaseTradeNtf struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Header          *MessageHead `protobuf:"bytes,1,opt,name=Header" json:"Header,omitempty"`                    // 消息头
+	WRTradeDetailID *uint64      `protobuf:"varint,2,opt,name=WRTradeDetailID" json:"WRTradeDetailID,omitempty"` // uint64 预售成交明细ID
+}
+
+func (x *THJPurchaseTradeNtf) Reset() {
+	*x = THJPurchaseTradeNtf{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_mtp2_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *THJPurchaseTradeNtf) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*THJPurchaseTradeNtf) ProtoMessage() {}
+
+func (x *THJPurchaseTradeNtf) ProtoReflect() protoreflect.Message {
+	mi := &file_mtp2_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use THJPurchaseTradeNtf.ProtoReflect.Descriptor instead.
+func (*THJPurchaseTradeNtf) Descriptor() ([]byte, []int) {
+	return file_mtp2_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *THJPurchaseTradeNtf) GetHeader() *MessageHead {
+	if x != nil {
+		return x.Header
+	}
+	return nil
+}
+
+func (x *THJPurchaseTradeNtf) GetWRTradeDetailID() uint64 {
+	if x != nil && x.WRTradeDetailID != nil {
+		return *x.WRTradeDetailID
+	}
+	return 0
+}
+
+var File_mtp2_proto protoreflect.FileDescriptor
+
+var file_mtp2_proto_rawDesc = []byte{
+	0x0a, 0x0a, 0x6d, 0x74, 0x70, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62,
+	0x22, 0xc7, 0x02, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64,
+	0x12, 0x18, 0x0a, 0x07, 0x46, 0x75, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0d, 0x52, 0x07, 0x46, 0x75, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x6f,
+	0x75, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x41, 0x63, 0x63,
+	0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+	0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+	0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69,
+	0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x47, 0x6f, 0x6f, 0x64, 0x73, 0x49, 0x44, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x07, 0x47, 0x6f, 0x6f, 0x64, 0x73, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04,
+	0x55, 0x55, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, 0x49, 0x44,
+	0x12, 0x1a, 0x0a, 0x08, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x49, 0x44, 0x18, 0x08, 0x20, 0x01,
+	0x28, 0x0d, 0x52, 0x08, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06,
+	0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x73,
+	0x65, 0x72, 0x49, 0x44, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x63,
+	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
+	0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x32, 0x22, 0x68, 0x0a, 0x13, 0x54, 0x48,
+	0x4a, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, 0x4e, 0x74,
+	0x66, 0x12, 0x27, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65,
+	0x61, 0x64, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0f, 0x57, 0x52,
+	0x54, 0x72, 0x61, 0x64, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x49, 0x44, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x0f, 0x57, 0x52, 0x54, 0x72, 0x61, 0x64, 0x65, 0x44, 0x65, 0x74, 0x61,
+	0x69, 0x6c, 0x49, 0x44,
+}
+
+var (
+	file_mtp2_proto_rawDescOnce sync.Once
+	file_mtp2_proto_rawDescData = file_mtp2_proto_rawDesc
+)
+
+func file_mtp2_proto_rawDescGZIP() []byte {
+	file_mtp2_proto_rawDescOnce.Do(func() {
+		file_mtp2_proto_rawDescData = protoimpl.X.CompressGZIP(file_mtp2_proto_rawDescData)
+	})
+	return file_mtp2_proto_rawDescData
+}
+
+var file_mtp2_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_mtp2_proto_goTypes = []interface{}{
+	(*MessageHead)(nil),         // 0: pb.MessageHead
+	(*THJPurchaseTradeNtf)(nil), // 1: pb.THJPurchaseTradeNtf
+}
+var file_mtp2_proto_depIdxs = []int32{
+	0, // 0: pb.THJPurchaseTradeNtf.Header:type_name -> pb.MessageHead
+	1, // [1:1] is the sub-list for method output_type
+	1, // [1:1] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_mtp2_proto_init() }
+func file_mtp2_proto_init() {
+	if File_mtp2_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_mtp2_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MessageHead); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_mtp2_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*THJPurchaseTradeNtf); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_mtp2_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_mtp2_proto_goTypes,
+		DependencyIndexes: file_mtp2_proto_depIdxs,
+		MessageInfos:      file_mtp2_proto_msgTypes,
+	}.Build()
+	File_mtp2_proto = out.File
+	file_mtp2_proto_rawDesc = nil
+	file_mtp2_proto_goTypes = nil
+	file_mtp2_proto_depIdxs = nil
+}

+ 24 - 0
res/pb/mtp2.proto

@@ -0,0 +1,24 @@
+syntax = "proto2";
+
+package pb;
+
+// 消息头
+message MessageHead {
+	optional uint32 FunCode = 1; // 功能号
+	optional uint32 RequestID = 2; // 客户端的流水ID
+	optional uint64 AccountID = 3; // 账号ID
+	optional uint32 AccessID = 4; //二级分配给客户端的接入ID
+	optional int64 ClientTime = 5; //消息发起时间
+	optional uint32 GoodsID = 6; //商品ID
+	optional string UUID = 7; // 消息唯一ID
+	optional uint32 MarketID = 8; // 所属市场ID
+	optional uint32 UserID = 9; // 用户ID
+	optional string ResponseTopic = 10; // 应答消息所属主题
+	optional uint64 AccountID2 = 11; // 账号ID-币币交易使用
+}
+
+// 铁合金成交通知
+message THJPurchaseTradeNtf {
+	optional MessageHead Header = 1; // 消息头
+		optional uint64 WRTradeDetailID = 2; // uint64 预售成交明细ID
+}

BIN
res/pb/protoc-gen-go.exe


BIN
res/pb/protoc.exe


+ 64 - 0
service/common.go

@@ -0,0 +1,64 @@
+package service
+
+import (
+	"fmt"
+	"mtp20_assisted/core"
+	"mtp20_assisted/global"
+
+	"go.uber.org/zap"
+)
+
+// InitRabbitMQMsgPreccesser 构建总线信息处理器
+func InitRabbitMQMsgPreccesser() (err error) {
+	global.M2A_MSGPROCESSER = make(map[string]global.MsgProcesser)
+
+	// 铁合金服务通知
+	// t := THJNtf{}
+	// global.M2A_MSGPROCESSER[global.TOPIC_THJ_NTF] = &t
+	t := new(THJNtf)
+	global.M2A_MSGPROCESSER[global.TOPIC_THJ_NTF] = t
+
+	return
+}
+
+// StartRabbitMQSubscribe 开始向总线创建和绑定队列
+func StartRabbitMQSubscribe() (err error) {
+	// 订阅需要的总线主题
+	if err = subscribeTopic(global.TOPIC_THJ_NTF); err != nil {
+		global.M2A_LOG.Error("rabbitmq subscribe topic failed, err:", zap.Error(err))
+		return
+	}
+	global.M2A_LOG.Info("rabbitmq subscribe topic success.")
+
+	return
+}
+
+// StartRabbitMQReceive 开始接收总线消息
+func StartRabbitMQReceive() {
+	go func() {
+		for topic, processer := range global.M2A_MSGPROCESSER {
+			core.Receive(topic, processer)
+		}
+	}()
+	global.M2A_LOG.Info("rabbitmq start receiving messages.")
+}
+
+// subscribeTopic 订阅主题
+func subscribeTopic(topic string) (err error) {
+	// 创建队列名称
+	queuename := fmt.Sprintf("mtp20_assisted_%s", topic)
+
+	// 申明队列
+	if _, err = global.M2A_RABBITMQ.Channel.QueueDeclare(queuename, true, false, false, true, nil); err != nil {
+		global.M2A_LOG.Error("rabbitmq declear queue failed, err:", zap.Error(err))
+		return
+	}
+
+	// 绑定队列
+	if err = global.M2A_RABBITMQ.Channel.QueueBind(queuename, topic, "entry", false, nil); err != nil {
+		global.M2A_LOG.Error("rabbitmq bind queue failed, err:", zap.Error(err))
+		return
+	}
+
+	return
+}

+ 148 - 0
service/thjNtf.go

@@ -0,0 +1,148 @@
+package service
+
+import (
+	"encoding/hex"
+	"mtp20_assisted/global"
+	"mtp20_assisted/model"
+	"mtp20_assisted/res/pb"
+	"mtp20_assisted/utils"
+	"strconv"
+	"time"
+
+	"github.com/nguyenthenguyen/docx"
+	"go.uber.org/zap"
+	"google.golang.org/protobuf/proto"
+)
+
+// THJNtf 铁合通知处理模型
+type THJNtf struct{}
+
+func (t *THJNtf) Process(msg *[]byte) {
+	// 分解总线包信息
+	funcode := utils.BytesToUint32((*msg)[0:4])
+	sessionId := utils.BytesToUint32((*msg)[4:8])
+	bytes := (*msg)[8:]
+	global.M2A_LOG.Info("[S->C]", zap.Any("funcode", funcode), zap.Any("sessionId", sessionId), zap.Any("count", len(bytes)))
+
+	switch funcode {
+	case uint32(global.THJPurchaseTradeNtf):
+		// 等待两秒
+		<-time.After(2 * time.Second)
+		onTHJPurchaseTradeNtf(&bytes)
+	}
+}
+
+// onTHJPurchaseTradeNtf 铁合金成交通知
+func onTHJPurchaseTradeNtf(bytes *[]byte) {
+	// Read from docx file
+	r, err := docx.ReadDocxFile("./static/现货预售合同.doc")
+	if err != nil {
+		global.M2A_LOG.Error("读取合同文件失败", zap.Error(err))
+		return
+	}
+
+	var p pb.THJPurchaseTradeNtf
+	if err := proto.Unmarshal(*bytes, &p); err != nil {
+		global.M2A_LOG.Error("总线回复数据反序列化失败", zap.Error(err))
+		return
+	}
+
+	// 铁合金采购成交扩展信息
+	thjpurchasetradedetail := model.Thjpurchasetradedetail{WRTRADEDETAILID: int64(p.GetWRTradeDetailID())}
+	if has, err := thjpurchasetradedetail.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取铁合金采购成交扩展信息失败", zap.Error(err))
+		return
+	}
+	// 交割方式
+	thjdeliverymode := "否"
+	if thjpurchasetradedetail.THJDELIVERYMODE == 1 {
+		thjdeliverymode = "是"
+	}
+
+	// 现货商品信息
+	wrstandard := model.Wrstandard{WRSTANDARDID: int64(thjpurchasetradedetail.WRSTANDARDID)}
+	if has, err := wrstandard.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取现货商品信息失败", zap.Error(err))
+		return
+	}
+
+	// 仓单预售信息
+	wrpresaleinfo := model.Wrpresaleinfo{PRESALEAPPLYID: thjpurchasetradedetail.PRESALEAPPLYID}
+	if has, err := wrpresaleinfo.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取仓单预售信息失败", zap.Error(err))
+		return
+	}
+
+	// 甲方信息
+	userinfo := model.Userinfo{USERID: thjpurchasetradedetail.BUYUSERID}
+	if has, err := userinfo.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取甲方信息失败", zap.Error(err))
+		return
+	}
+	division := model.Division{AUTOID: int64(userinfo.DISTRICTID)}
+	totalAddress, err := division.GetTotalAddressByDistrictID(userinfo.ADDRESS)
+	if err != nil {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取甲方地址信息失败", zap.Error(err))
+		return
+	}
+	// 证件号码解密
+	key, _ := hex.DecodeString(utils.AESSecretKey)
+	if len(userinfo.CARDNUM) > 0 {
+		if cardnum, err := hex.DecodeString(userinfo.CARDNUM); err == nil { // hex -> []byte
+			if c, err := utils.AESDecrypt(cardnum, key); err == nil {
+				userinfo.CARDNUM = string(c)
+			}
+		}
+	}
+	// 手机号码解密
+	if len(userinfo.MOBILE) > 0 {
+		if phonenum, err := hex.DecodeString(userinfo.MOBILE); err == nil { // hex -> []byte
+			if mobile, err := utils.AESDecrypt(phonenum, key); err == nil {
+				userinfo.MOBILE = string(mobile)
+			}
+		}
+	}
+
+	// 甲方签约信息
+	bankaccountsign := model.Bankaccountsign{}
+	if has, err := bankaccountsign.GetByUserID(uint64(thjpurchasetradedetail.BUYUSERID)); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取甲方签约信息失败", zap.Error(err))
+		return
+	}
+	// 银行信息
+	bankinfo := model.Bankbankinfo{BANKID: bankaccountsign.BANKID}
+	if has, err := bankinfo.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取银行信息失败", zap.Error(err))
+		return
+	}
+
+	// 生产厂家信息
+	selluserinfo := model.Userinfo{USERID: thjpurchasetradedetail.SELLUSERID}
+	if has, err := selluserinfo.Get(); err != nil || !has {
+		global.M2A_LOG.Error("[onTHJPurchaseTradeNtf] 获取生产厂家信息失败", zap.Error(err))
+		return
+	}
+
+	docx1 := r.Editable()
+	docx1.Replace("${WRTRADEDETAILID}", strconv.Itoa(int(thjpurchasetradedetail.WRTRADEDETAILID)), -1)
+	docx1.Replace("${TRADETIME}", thjpurchasetradedetail.TRADETIME.Format("2006年01月02日"), -1)
+	docx1.Replace("${DESADDRESS}", totalAddress, -1)
+	docx1.Replace("${CUSTOMERNAME}", userinfo.CUSTOMERNAME, -1)
+	docx1.Replace("${CARDNUM}", userinfo.CARDNUM, -1)
+	docx1.Replace("${MOBILE}", userinfo.MOBILE, -1)
+	docx1.Replace("${BANK}", bankinfo.BANKNAME, -1)
+	docx1.Replace("${BANKACCOUNTNO}", bankaccountsign.BANKACCOUNTNO, -1)
+	docx1.Replace("${WRSTANDARDNAME}", wrstandard.WRSTANDARDNAME, -1)
+	docx1.Replace("${SELLUSER}", selluserinfo.CUSTOMERNAME, -1)
+	docx1.Replace("${LASTAMOUNT}", strconv.FormatFloat(thjpurchasetradedetail.LASTAMOUNT, 'f', -1, 64), -1)
+	docx1.Replace("${DEPOSITRATE}", strconv.FormatFloat(thjpurchasetradedetail.DEPOSITRATE, 'f', -1, 64), -1)
+	docx1.Replace("${TRADEQTY}", strconv.Itoa(int(thjpurchasetradedetail.TRADEQTY)), -1)
+	docx1.Replace("${TRADEPRICE}", strconv.FormatFloat(thjpurchasetradedetail.TRADEPRICE, 'f', -1, 64), -1)
+	docx1.Replace("${ENDDATEMONTH}", strconv.Itoa(int(wrpresaleinfo.ENDDATE.Local().Month())), -1)
+	docx1.Replace("${THJDELIVERYMODE}", thjdeliverymode, -1)
+	docx1.Replace("${ENDDATE}", wrpresaleinfo.ENDDATE.Format("2006年01月"), -1)
+	docx1.Replace("${STORAGEFEE}", strconv.FormatFloat(wrstandard.STORAGEFEE, 'f', -1, 64), -1)
+
+	docx1.WriteToFile("./new_result_1.doc")
+	r.Close()
+}

BIN
static/协议转让电子合同模板.docx


BIN
static/现货贸易合同(买家模板).doc


BIN
static/现货贸易合同(卖家模板).doc


BIN
static/现货预售合同.doc


+ 150 - 0
utils/bytes.go

@@ -0,0 +1,150 @@
+package utils
+
+import (
+	"bytes"
+	"encoding/binary"
+	"encoding/json"
+)
+
+// IntToBytes int to []bytes littleEndian
+func IntToBytes(n int32) []byte {
+	x := int32(n)
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.LittleEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+// UintToBytes  uint to []bytes littleEndian
+func UintToBytes(n uint32) []byte {
+	x := uint32(n)
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.LittleEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+// UintTobytesBigEnd uint to []bytes bigEndian
+func UintTobytesBigEnd(n uint32) []byte {
+	x := uint32(n)
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.BigEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+// Int32TobytesBigEnd int32 to []bytes bigEndian
+func Int32TobytesBigEnd(n int32) []byte {
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.BigEndian, n)
+	return bytesBuffer.Bytes()
+}
+
+// Uint64ToBytes to []bytes
+func Uint64ToBytes(n uint64) []byte {
+	x := n
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.LittleEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+// Uint64ToBytesBigEnd to []bytes
+func Uint64ToBytesBigEnd(n uint64) []byte {
+	x := n
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.BigEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+// BytesToInt 字节转换成整形
+func BytesToInt(b []byte) int32 {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x int32
+	_ = binary.Read(bytesBuffer, binary.LittleEndian, &x)
+
+	return x
+}
+
+//BytesToUint32 to []bytes
+func BytesToUint32(b []byte) uint32 {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x int32
+	_ = binary.Read(bytesBuffer, binary.LittleEndian, &x)
+
+	return uint32(x)
+}
+
+//BytesBigEndToUint32 to uint
+func BytesBigEndToUint32(b []byte) uint32 {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x int32
+	_ = binary.Read(bytesBuffer, binary.BigEndian, &x)
+
+	return uint32(x)
+}
+
+//Uint16TobytesBigEnd to []bytes
+func Uint16TobytesBigEnd(n uint16) []byte {
+	x := uint16(n)
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	_ = binary.Write(bytesBuffer, binary.BigEndian, x)
+	return bytesBuffer.Bytes()
+}
+
+//BytesBigEndToUint16 to uint16
+func BytesBigEndToUint16(b []byte) uint16 {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x int16
+	_ = binary.Read(bytesBuffer, binary.BigEndian, &x)
+
+	return uint16(x)
+}
+
+//BytesBigEndToUint64 to uint64
+func BytesBigEndToUint64(b []byte) uint64 {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x uint64
+	_ = binary.Read(bytesBuffer, binary.BigEndian, &x)
+
+	return x
+}
+
+//HTONL32 转换为网络字节序
+func HTONL32(v uint32) []byte {
+	return UintTobytesBigEnd(v)
+}
+
+//HTONLint32 转换为网络字节序
+func HTONLInt32(v int32) []byte {
+	return Int32TobytesBigEnd(v)
+}
+
+//HTONS 转换为网络字节序
+func HTONS(v uint16) []byte {
+	return Uint16TobytesBigEnd(v)
+}
+
+//NTOHL32 转换为主机字节序
+func NTOHL32(buf []byte) uint32 {
+	return BytesBigEndToUint32(buf)
+}
+
+//NTOHL64 转换为主机字节序
+func NTOHL64(buf []byte) uint64 {
+	return BytesBigEndToUint64(buf)
+}
+
+//NTOHS 主机字节序
+func NTOHS(buf []byte) uint16 {
+	return BytesBigEndToUint16(buf)
+}
+
+//DebugString 结构体对应的Json串
+func DebugString(v interface{}) string {
+	if buf, err := json.MarshalIndent(v, " ", " "); err == nil {
+		return string(buf)
+	}
+	return ""
+}

+ 115 - 0
utils/encryptUtils.go

@@ -0,0 +1,115 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"errors"
+)
+
+// AESSecretKey AES密钥
+const AESSecretKey = "0d299ce2d4105282f7471074cb0f9f9d"
+
+// AESEncrypt AES加密
+func AESEncrypt(plaintext, key []byte) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, errors.New("错误的数据或密钥")
+	}
+	ecb := NewECBEncrypter(block)
+	content := plaintext[:]
+	content = PKCS5Padding(content, block.BlockSize())
+	crypted := make([]byte, len(content))
+	ecb.CryptBlocks(crypted, content)
+
+	return crypted, nil
+}
+
+// AESDecrypt AES
+func AESDecrypt(crypted, key []byte) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, errors.New("错误的数据或密钥")
+	}
+	blockMode := NewECBDecrypter(block)
+	origData := make([]byte, len(crypted))
+	blockMode.CryptBlocks(origData, crypted)
+	origData = PKCS5UnPadding(origData)
+
+	return origData, nil
+}
+
+// PKCS5Padding ECB PKCS5Padding
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+// PKCS5UnPadding ECB PKCS5Unpadding
+func PKCS5UnPadding(origData []byte) []byte {
+	length := len(origData)
+	// 去掉最后一个字节 unpadding 次
+	unpadding := int(origData[length-1])
+	// 防止数据越界崩溃
+	if length-unpadding >= len(origData) {
+		return origData
+	}
+	return origData[:(length - unpadding)]
+}
+
+type ecb struct {
+	b         cipher.Block
+	blockSize int
+}
+
+func newECB(b cipher.Block) *ecb {
+	return &ecb{
+		b:         b,
+		blockSize: b.BlockSize(),
+	}
+}
+
+type ecbEncrypter ecb
+
+// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
+// mode, using the given Block.
+func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbEncrypter)(newECB(b))
+}
+func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
+func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	for len(src) > 0 {
+		x.b.Encrypt(dst, src[:x.blockSize])
+		src = src[x.blockSize:]
+		dst = dst[x.blockSize:]
+	}
+}
+
+type ecbDecrypter ecb
+
+// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
+// mode, using the given Block.
+func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbDecrypter)(newECB(b))
+}
+func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
+func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	for len(src) > 0 {
+		x.b.Decrypt(dst, src[:x.blockSize])
+		src = src[x.blockSize:]
+		dst = dst[x.blockSize:]
+	}
+}