hsby.go 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  1. package models
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "math"
  6. "mtp2_if/db"
  7. "mtp2_if/utils"
  8. "strconv"
  9. "time"
  10. )
  11. // Hsbygoodsex 商品扩展表
  12. type Hsbygoodsex struct {
  13. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商 品ID
  14. Hotindex int32 `json:"hotindex" xorm:"'HOTINDEX'"` // 景点热度
  15. Descprovinceid int64 `json:"descprovinceid" xorm:"'DESCPROVINCEID'"` // 目的地(省)
  16. Desccityid int64 `json:"desccityid" xorm:"'DESCCITYID'"` // 目的地(市)
  17. Vendorid int32 `json:"vendorid" xorm:"'VENDORID'"` // 供应商ID
  18. Goodsdesc string `json:"goodsdesc" xorm:"'GOODSDESC'"` // 商品详情
  19. Createtime time.Time `json:"createtime" xorm:"'CREATETIME'"` // 创建时间
  20. Creatorid int64 `json:"creatorid" xorm:"'CREATORID'"` // 创建人
  21. Modifierid int64 `json:"modifierid" xorm:"'MODIFIERID'"` // 修改人
  22. Modifytime time.Time `json:"modifytime" xorm:"'MODIFYTIME'"` // 修改时间
  23. Memberratio float64 `json:"memberratio" xorm:"'MEMBERRATIO'"` // 会员货款比例 [71]
  24. Videourls string `json:"videourls" xorm:"'VIDEOURLS'"` // 介绍视频[多张用逗号分隔]
  25. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  26. }
  27. // TableName is HSBY_GOODSEX
  28. func (Hsbygoodsex) TableName() string {
  29. return "HSBY_GOODSEX"
  30. }
  31. // Hsbysupplierinfo 供应商表
  32. type Hsbysupplierinfo struct {
  33. Vendorid int32 `json:"vendorid" xorm:"'VENDORID'" binding:"required"` // 供应商ID(SEQ_HSBY_SUPPLIERINFO)
  34. Vendorname string `json:"vendorname" xorm:"'VENDORNAME'"` // 名称描述客服电话名称
  35. Vendordesc string `json:"vendordesc" xorm:"'VENDORDESC'"` // 描述
  36. Vendorphone string `json:"vendorphone" xorm:"'VENDORPHONE'"` // 客服电话
  37. Vendorattr string `json:"vendorattr" xorm:"'VENDORATTR'"` // 附件(多张,逗号分隔)
  38. Createtime time.Time `json:"createtime" xorm:"'CREATETIME'"` // 创建时间
  39. Creatorid int64 `json:"creatorid" xorm:"'CREATORID'"` // 创建人
  40. Modifierid int64 `json:"modifierid" xorm:"'MODIFIERID'"` // 修改人
  41. Modifytime time.Time `json:"modifytime" xorm:"'MODIFYTIME'"` // 修改时间
  42. }
  43. // TableName is HSBY_SUPPLIERINFO
  44. func (Hsbysupplierinfo) TableName() string {
  45. return "HSBY_SUPPLIERINFO"
  46. }
  47. // HsbyTopGoods 热卖商品(二级市场挂牌点选)
  48. type HsbyTopGoods struct {
  49. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID(自增ID SEQ_GOODS)
  50. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  51. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  52. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  53. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 所属市场ID
  54. Quoteminunit int64 `json:"quoteminunit" xorm:"'QUOTEMINUNIT'"` // 行情最小变动单位 [整数,报价小数位一起使用]
  55. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  56. Hotindex int32 `json:"hotindex" xorm:"'HOTINDEX'"` // 景点热度
  57. Videourls string `json:"videourls" xorm:"'VIDEOURLS'"` // 介绍视频[多张用逗号分隔]
  58. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  59. Currency string `json:"currency" xorm:"'CURRENCY'"` // 货币
  60. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  61. Trademode int32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  62. Last float64 `json:"last" xorm:"-"` // 现价
  63. }
  64. // GetHsbyTopGoodses 获取热门商品列表
  65. // 参数 marketIDs string 所属市场ID列表, 格式 1,2,3
  66. // 参数 descProvinceID int 目标省ID
  67. // 参数 descCityID int 目标城市ID
  68. // 返回 []TopGoods 热门商品列表
  69. // 返回 error error
  70. func GetHsbyTopGoodses(marketIDs string, descProvinceID, descCityID int) ([]HsbyTopGoods, error) {
  71. // 热门商品为二级市场(挂牌点选)下的商品信息
  72. engine := db.GetEngine()
  73. topGoodses := make([]HsbyTopGoods, 0)
  74. // 获取挂牌商品信息,以及扩展表信息
  75. session := engine.Table("GOODS").
  76. Select(`GOODS.*,
  77. HSBY_GOODSEX.HOTINDEX, HSBY_GOODSEX.VIDEOURLS, HSBY_GOODSEX.PICURLS,
  78. ENUMDICITEM.ENUMDICNAME CURRENCY, ENUMDICITEM.PARAM2 CURRENCYSIGN,
  79. MARKET.TRADEMODE`).
  80. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  81. Join("LEFT", "ENUMDICITEM", "ENUMDICITEM.ENUMITEMNAME = GOODS.CURRENCYID and ENUMDICITEM.ENUMDICCODE = 'currency'").
  82. Join("LEFT", "MARKET", "MARKET.MARKETID = GOODS.MARKETID").
  83. Where(fmt.Sprintf("GOODS.GOODSSTATUS = 3 and GOODS.MARKETID in (%s)", marketIDs)) // 二级市场只获取 3:上市 状态的商品
  84. if descProvinceID > 0 {
  85. session = session.And("HSBY_GOODSEX.DESCPROVINCEID = ?", descProvinceID)
  86. }
  87. if descCityID > 0 {
  88. session = session.And("HSBY_GOODSEX.DESCCITYID = ?", descCityID)
  89. }
  90. if err := session.Find(&topGoodses); err != nil {
  91. return nil, err
  92. }
  93. if len(topGoodses) == 0 {
  94. // 无数据
  95. return topGoodses, nil
  96. }
  97. // 获取商品ID列表
  98. goodsCodes := ""
  99. for _, v := range topGoodses {
  100. if len(goodsCodes) == 0 {
  101. goodsCodes = v.Goodscode
  102. } else {
  103. goodsCodes += "," + v.Goodscode
  104. }
  105. }
  106. // 获取商品现价
  107. quoteDays, err := GetQuoteDays(goodsCodes)
  108. if err != nil {
  109. return nil, err
  110. }
  111. for i, g := range topGoodses {
  112. topGoods := &topGoodses[i]
  113. // FIXME: - 这里应该使用 Duck Typing,后期再处理
  114. // 计算最小变动单位
  115. // lotSize := float64(topGoods.Quoteminunit) * math.Pow(0.1, float64(topGoods.Decimalplace))
  116. // topGoods.LotSize, _ = strconv.ParseFloat(utils.FormatFloat(lotSize, int(topGoods.Decimalplace)), 64)
  117. for _, q := range quoteDays {
  118. if g.Goodscode == q.Goodscode {
  119. if q.Last != 0 {
  120. topGoods.Last = utils.IntToFloat64(int(q.Last), int(g.Decimalplace))
  121. }
  122. // 没有现价则尝试用昨结
  123. if topGoods.Last == 0 && q.Presettle != 0 {
  124. topGoods.Last = utils.IntToFloat64(int(q.Presettle), int(g.Decimalplace))
  125. }
  126. continue
  127. }
  128. }
  129. }
  130. return topGoodses, nil
  131. }
  132. // HsbyListingGoodsDetail 二级市场(挂牌点选)商品信息详情
  133. type HsbyListingGoodsDetail struct {
  134. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID(自增ID SEQ_GOODS)
  135. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  136. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  137. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  138. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 所属市场ID
  139. Quoteminunit int64 `json:"quoteminunit" xorm:"'QUOTEMINUNIT'"` // 行情最小变动单位 [整数,报价小数位一起使用]
  140. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  141. Hotindex int32 `json:"hotindex" xorm:"'HOTINDEX'"` // 景点热度
  142. Videourls string `json:"videourls" xorm:"'VIDEOURLS'"` // 介绍视频[多张用逗号分隔]
  143. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  144. Descprovinceid int64 `json:"descprovinceid" xorm:"'DESCPROVINCEID'"` // 目的地(省)ID
  145. Desccityid int64 `json:"desccityid" xorm:"'DESCCITYID'"` // 目的地(市)ID
  146. Goodsdesc string `json:"goodsdesc" xorm:"'GOODSDESC'"` // 商品详情
  147. Currency string `json:"currency" xorm:"'CURRENCY'"` // 货币
  148. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  149. Vendorname string `json:"vendorname" xorm:"'VENDORNAME'"` // 供应商名称
  150. Vendorphone string `json:"vendorphone" xorm:"'VENDORPHONE'"` // 供应商客服电话
  151. Vendorattr string `json:"vendorattr" xorm:"'VENDORATTR'"` // 供应商附件(多张,逗号分隔)
  152. Trademode int32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  153. Last float64 `json:"last" xorm:"-"` // 现价
  154. Limitup float64 `json:"limitup" xorm:"-"` // 涨停价
  155. Limitdown float64 `json:"limitdown" xorm:"-"` // 跌停价
  156. StepValue float64 `json:"stepvalue" xorm:"-"` // 价格最小变动单位
  157. LotSize int `json:"lotsize" xorm:"-"` // 手数最小变动单位
  158. }
  159. // GetHsbyListingGoodsDetail 获取二级市场(挂牌点选)商品信息详情
  160. // 参数 goodsID int 目标商品ID
  161. // 返回 *HsbyListingGoodsDetail 二级市场(挂牌点选)商品信息详情,查询无结果返回nil
  162. // 返回 error error
  163. func GetHsbyListingGoodsDetail(goodsID int) (*HsbyListingGoodsDetail, error) {
  164. engine := db.GetEngine()
  165. details := make([]HsbyListingGoodsDetail, 0)
  166. // 获取挂牌商品信息,以及扩展表信息
  167. // FIXME: - 这里使用Get方法,会造成SQL语句的嵌套出错,后期再研究
  168. session := engine.Table("GOODS").
  169. Select(`GOODS.GOODSID, GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.MARKETID, GOODS.QUOTEMINUNIT, GOODS.AGREEUNIT,
  170. HSBY_GOODSEX.HOTINDEX, HSBY_GOODSEX.VIDEOURLS, HSBY_GOODSEX.PICURLS, HSBY_GOODSEX.DESCPROVINCEID, HSBY_GOODSEX.Desccityid, HSBY_GOODSEX.Goodsdesc,
  171. ENUMDICITEM.ENUMDICNAME CURRENCY, ENUMDICITEM.PARAM2 CURRENCYSIGN,
  172. HSBY_SUPPLIERINFO.VENDORNAME, HSBY_SUPPLIERINFO.VENDORPHONE, HSBY_SUPPLIERINFO.VENDORATTR,
  173. MARKET.TRADEMODE`).
  174. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  175. Join("LEFT", "ENUMDICITEM", "ENUMDICITEM.ENUMITEMNAME = GOODS.CURRENCYID and ENUMDICITEM.ENUMDICCODE = 'currency'").
  176. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  177. Join("LEFT", "MARKET", "MARKET.MARKETID = GOODS.MARKETID").
  178. Where("GOODS.GOODSID = ?", goodsID)
  179. if err := session.Find(&details); err != nil {
  180. return nil, err
  181. }
  182. // 无目标商品
  183. if len(details) == 0 {
  184. return nil, nil
  185. }
  186. hsbyListingGoodsDetail := details[0]
  187. // 获取商品现价和涨跌停价
  188. quoteDays, err := GetQuoteDays(hsbyListingGoodsDetail.Goodscode)
  189. if err != nil {
  190. return nil, err
  191. }
  192. if len(quoteDays) > 0 {
  193. if quoteDays[0].Last != 0 {
  194. hsbyListingGoodsDetail.Last = utils.IntToFloat64(int(quoteDays[0].Last), int(hsbyListingGoodsDetail.Decimalplace))
  195. }
  196. // 没有现价则尝试用昨结
  197. if hsbyListingGoodsDetail.Last == 0 && quoteDays[0].Presettle != 0 {
  198. hsbyListingGoodsDetail.Last = utils.IntToFloat64(int(quoteDays[0].Presettle), int(hsbyListingGoodsDetail.Decimalplace))
  199. }
  200. if quoteDays[0].Limitup != 0 {
  201. hsbyListingGoodsDetail.Limitup = utils.IntToFloat64(int(quoteDays[0].Limitup), int(hsbyListingGoodsDetail.Decimalplace))
  202. }
  203. if quoteDays[0].Limitdown != 0 {
  204. hsbyListingGoodsDetail.Limitdown = utils.IntToFloat64(int(quoteDays[0].Limitdown), int(hsbyListingGoodsDetail.Decimalplace))
  205. }
  206. }
  207. // 计算价格最小变动单位
  208. stepValue := float64(hsbyListingGoodsDetail.Quoteminunit) * math.Pow(0.1, float64(hsbyListingGoodsDetail.Decimalplace))
  209. hsbyListingGoodsDetail.StepValue, _ = strconv.ParseFloat(utils.FormatFloat(stepValue, int(hsbyListingGoodsDetail.Decimalplace)), 64)
  210. // 计算手数最小变动单位
  211. hsbyListingGoodsDetail.LotSize = 1
  212. return &hsbyListingGoodsDetail, nil
  213. }
  214. // HsbyGoodsOrderDetail 二级市场挂牌商品当前可摘委托单信息
  215. type HsbyGoodsOrderDetail struct {
  216. Orderid string `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  217. Buyorsell int32 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  218. Ordertime time.Time `json:"ordertime" xorm:"'ORDERTIME'" binding:"required"` // 委托时间
  219. Orderprice float64 `json:"orderprice" xorm:"'ORDERPRICE'"` // 委托价格
  220. Enableqty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 可用数量
  221. Customername string `json:"customername" xorm:"'CUSTOMERNAME'"` // 客户名称(企业名称),已脱敏
  222. Currencysign string `json:"currencysign" xorm:"-"` // 货币符号
  223. Goodunit string `json:"goodunit" xorm:"-"` // 报价单位
  224. }
  225. // GetHsbyGoodsOrderDetails 获取二级市场(挂牌点选)商品对应的挂牌委托单信息
  226. // 输入 goodsID int 商品ID
  227. // 输入 buyOrSell int 挂牌委托单方向(对手单方向),0:买 1:卖
  228. // 输入 price float64 参考价格。买方向委托单则价格小于等于(站在摘牌人的角度);卖方向委托单则价格大于等于
  229. // 输出 []HsbyGoodsOrderDetail 商品对应的挂牌委托单信息
  230. // 输出 error error
  231. func GetHsbyGoodsOrderDetails(goodsID, buyOrSell int, price float64, accountIDs string) ([]HsbyGoodsOrderDetail, error) {
  232. engine := db.GetEngine()
  233. // 获取与目标商品相关的挂牌委托单信息(ListingSelectType = 1 or 3; OrderStatus =3 or 7)
  234. hsbyGoodsOrderDetails := make([]HsbyGoodsOrderDetail, 0)
  235. session := engine.Table("TRADE_ORDERDETAIL").
  236. Select(`to_char(TRADE_ORDERDETAIL.ORDERID) ORDERID, TRADE_ORDERDETAIL.BUYORSELL, TRADE_ORDERDETAIL.ORDERTIME, TRADE_ORDERDETAIL.ORDERPRICE, (TRADE_ORDERDETAIL.ORDERQTY - TRADE_ORDERDETAIL.TRADEQTY - TRADE_ORDERDETAIL.CANCELQTY) ENABLEQTY,
  237. substr(USERINFO.CUSTOMERNAME,0,1)||'****' as CUSTOMERNAME`).
  238. Join("LEFT", "TAACCOUNT", "TAACCOUNT.ACCOUNTID = TRADE_ORDERDETAIL.ACCOUNTID").
  239. Join("LEFT", "USERINFO", "USERINFO.USERID = TAACCOUNT.RELATEDUSERID").
  240. Where("(TRADE_ORDERDETAIL.LISTINGSELECTTYPE = 1 or TRADE_ORDERDETAIL.LISTINGSELECTTYPE = 3) and (TRADE_ORDERDETAIL.ORDERSTATUS = 3 or TRADE_ORDERDETAIL.ORDERSTATUS = 7)").
  241. And("TRADE_ORDERDETAIL.GOODSID = ?", goodsID).
  242. And("TRADE_ORDERDETAIL.BUYORSELL = ?", buyOrSell).
  243. And(fmt.Sprintf("TRADE_ORDERDETAIL.ACCOUNTID not in (%s)", accountIDs))
  244. if price > 0 {
  245. if buyOrSell == 0 {
  246. // 对手单买方向委托单则价格大于等于(站在摘牌人的角度,摘牌方面是卖,我的闲置下单)
  247. session = session.And("TRADE_ORDERDETAIL.ORDERPRICE >= ?", price)
  248. } else {
  249. // 对手单卖方向委托单则价格小于等于(站在摘牌人的角度,摘牌方面是买,热门商品下单)
  250. session = session.And("TRADE_ORDERDETAIL.ORDERPRICE <= ?", price)
  251. }
  252. }
  253. if err := session.Find(&hsbyGoodsOrderDetails); err != nil {
  254. return nil, err
  255. }
  256. // 获取商品货币符号和报价单位
  257. goods, err := GetGoods(goodsID)
  258. if err != nil {
  259. return nil, err
  260. }
  261. currencyEnums, err := GetEnumDicItem("currency", int(goods.Currencyid))
  262. if err != nil {
  263. return nil, err
  264. }
  265. currencysign := ""
  266. if len(currencyEnums) > 0 {
  267. currencysign = currencyEnums[0].Param2
  268. }
  269. goodsUnitEnums, err := GetEnumDicItem("goodsunit", int(goods.Goodunitid))
  270. if err != nil {
  271. return nil, err
  272. }
  273. goodsUnit := ""
  274. if len(goodsUnitEnums) > 0 {
  275. goodsUnit = goodsUnitEnums[0].Enumdicname
  276. }
  277. for i := range hsbyGoodsOrderDetails {
  278. orderDetail := &hsbyGoodsOrderDetails[i]
  279. // 设置货币符号和报价单位
  280. orderDetail.Currencysign = currencysign
  281. orderDetail.Goodunit = goodsUnit
  282. }
  283. return hsbyGoodsOrderDetails, nil
  284. }
  285. // HybsMyBuyOrderDetail 我的订单(一二级市场的买方向委托单)
  286. type HybsMyBuyOrderDetail struct {
  287. Orderid string `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
  288. Marketid int32 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID
  289. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID
  290. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
  291. Buyorsell int32 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  292. Orderprice float64 `json:"orderprice" xorm:"'ORDERPRICE'"` // 委托价格
  293. Orderqty int64 `json:"orderqty" xorm:"'ORDERQTY'" binding:"required"` // 委托数量
  294. Tradeqty int64 `json:"tradeqty" xorm:"'TRADEQTY'"` // 成交数量
  295. Cancelqty int64 `json:"cancelqty" xorm:"'CANCELQTY'"` // 撤单数量
  296. Ordertime time.Time `json:"ordertime" xorm:"'ORDERTIME'" binding:"required"` // 委托时间
  297. Listingselecttype int32 `json:"listingselecttype" xorm:"'LISTINGSELECTTYPE'"` // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
  298. Orderstatus int32 `json:"orderstatus" xorm:"'ORDERSTATUS'"` // 委托状态 - 1: 委托请求 2:待冻结 3:委托成功 4: 委托失败 5:配对成功 6: 已撤销 7:部分成交 8:已成交 9:部成部撤 10:成交失败 11:已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用)
  299. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  300. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  301. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  302. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  303. Picurls1 string `json:"picurls1" xorm:"'PICURLS1'"` // 预售商品介绍图片[多张用逗号分隔]
  304. Picurls2 string `json:"picurls2" xorm:"'PICURLS2'"` // 挂牌商品介绍图片[多张用逗号分隔]
  305. Trademode uint32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  306. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  307. Vendorname1 string `json:"vendorname1" xorm:"'VENDORNAME1'"` // 预售商品供应商名称
  308. Vendorname2 string `json:"vendorname2" xorm:"'VENDORNAME2'"` // 挂牌商品供应商名称
  309. MyBuyStatus int `json:"mybuystatus" xorm:"-"` // "我的订单"显示状态- 1:抢购中 2:求购中 3:已完成 4:已撤消 5:委托失败
  310. Orderamount float64 `json:"orderamount" xorm:"-"` // 委托金额
  311. }
  312. // GetHsbyBuyMyOrderDetails 获取“我的订单”数据(包括一二级市场)
  313. // 输入 accountIDs string 资金账户列表
  314. // 输入 myBuyStatus int "我的订单"状态, 1:抢购中 2:求购中 3:已完成
  315. // 输出 []HybsMyBuyOrderDetail “我的订单”数据
  316. // 输出 error error
  317. func GetHsbyBuyMyOrderDetails(accountIDs string, myBuyStatus int) ([]HybsMyBuyOrderDetail, error) {
  318. // 获取市场信息
  319. markets, err := GetMarkets()
  320. if err != nil {
  321. return nil, err
  322. }
  323. engine := db.GetEngine()
  324. // 委托状态
  325. orderStatus := "0" // 单据状态,为0的时候查询全部
  326. marketIDs := "" // 我的订单包括一二级市场的单据
  327. switch myBuyStatus {
  328. case 1: // 抢购中 (一级市场)
  329. // 获取市场ID
  330. for _, v := range markets {
  331. if v.Trademode == 71 { // 预售挂牌
  332. if len(marketIDs) == 0 {
  333. marketIDs = strconv.Itoa(int(v.Marketid))
  334. } else {
  335. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  336. }
  337. }
  338. }
  339. orderStatus = "3,7"
  340. case 2: // 求购中(二级市场)
  341. // 获取市场ID
  342. for _, v := range markets {
  343. if v.Trademode == 16 { // 挂牌点选
  344. if len(marketIDs) == 0 {
  345. marketIDs = strconv.Itoa(int(v.Marketid))
  346. } else {
  347. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  348. }
  349. }
  350. }
  351. orderStatus = "3,7"
  352. case 3: // 已完成
  353. orderStatus = "8,9"
  354. }
  355. // 默认取 TradeMode = 16 or 71 的市场
  356. if len(marketIDs) == 0 {
  357. for _, v := range markets {
  358. if v.Trademode == 16 || v.Trademode == 71 {
  359. if len(marketIDs) == 0 {
  360. marketIDs = strconv.Itoa(int(v.Marketid))
  361. } else {
  362. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  363. }
  364. }
  365. }
  366. }
  367. hybsMyBuyOrderDetails := make([]HybsMyBuyOrderDetail, 0)
  368. // "我的订单"都是买委托
  369. session := engine.Table("TRADE_ORDERDETAIL").
  370. Select(`to_char(TRADE_ORDERDETAIL.ORDERID) ORDERID, TRADE_ORDERDETAIL.*,
  371. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  372. HG1.PICURLS PICURLS1,
  373. HG2.PICURLS PICURLS2,
  374. MARKET.TRADEMODE,
  375. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  376. HS1.VENDORNAME VENDORNAME1,
  377. HS2.VENDORNAME VENDORNAME2`).
  378. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID").
  379. Join("LEFT", "CPTRADE_PRESALEGOODSEX", "CPTRADE_PRESALEGOODSEX.GOODSID = TRADE_ORDERDETAIL.GOODSID").
  380. Join("LEFT", "HSBY_GOODSEX HG1", "HG1.GOODSID = CPTRADE_PRESALEGOODSEX.RELATEDGOODSID").
  381. Join("LEFT", "HSBY_GOODSEX HG2", "HG2.GOODSID = GOODS.GOODSID").
  382. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  383. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID").
  384. Join("LEFT", "HSBY_SUPPLIERINFO HS1", "HS1.VENDORID = HG1.VENDORID").
  385. Join("LEFT", "HSBY_SUPPLIERINFO HS2", "HS2.VENDORID = HG2.VENDORID").
  386. Where(fmt.Sprintf("TRADE_ORDERDETAIL.BUYORSELL = 0 and TRADE_ORDERDETAIL.ACCOUNTID in (%s)", accountIDs)).
  387. And(fmt.Sprintf("TRADE_ORDERDETAIL.MARKETID in (%s)", marketIDs))
  388. // 是否过滤状态(抢购中、求购中、已完成)
  389. if orderStatus != "0" {
  390. session = session.And(fmt.Sprintf("TRADE_ORDERDETAIL.ORDERSTATUS in (%s)", orderStatus))
  391. }
  392. if err := session.Find(&hybsMyBuyOrderDetails); err != nil {
  393. return nil, err
  394. }
  395. // 设置“我的订单”显示状态
  396. for i := range hybsMyBuyOrderDetails {
  397. detail := &hybsMyBuyOrderDetails[i]
  398. // 委托金额 = 委托价格 * 委托数量 * 合约单位
  399. detail.Orderamount = detail.Orderprice * float64(detail.Orderqty) * float64(detail.Agreeunit)
  400. if detail.Trademode == 71 && (detail.Orderstatus == 3 || detail.Orderstatus == 7) {
  401. // 抢购中
  402. detail.MyBuyStatus = 1
  403. } else if detail.Trademode == 16 && (detail.Orderstatus == 3 || detail.Orderstatus == 7) {
  404. // 求购中
  405. detail.MyBuyStatus = 2
  406. } else if detail.Orderstatus == 8 || detail.Orderstatus == 9 {
  407. // 已完成
  408. detail.MyBuyStatus = 3
  409. } else if detail.Orderstatus == 6 {
  410. // 已撤销
  411. detail.MyBuyStatus = 4
  412. } else if detail.Orderstatus == 4 {
  413. // 委托失败
  414. detail.MyBuyStatus = 5
  415. }
  416. }
  417. return hybsMyBuyOrderDetails, nil
  418. }
  419. // HsbyMyGoods 我的商品(买方向持仓)
  420. type HsbyMyGoods struct {
  421. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账号Id
  422. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品Id
  423. Buycurpositionqty int64 `json:"buycurpositionqty" xorm:"'BUYCURPOSITIONQTY'"` // 买当前持仓总数量
  424. Buycurholderamount float64 `json:"buycurholderamount" xorm:"'BUYCURHOLDERAMOUNT'"` // 买当前持仓总金额[商品币种]
  425. EnableQty int64 `json:"enableqty" xorm:"'ENABLEQTY'"` // 可用数量
  426. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  427. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  428. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  429. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  430. Goodsstatus int64 `json:"goodsstatus" xorm:"'GOODSSTATUS'"` // 商品状态- 1:待审核 2:未上市 3:上市 4:已注销 5:审核拒绝 6:退市 7:待退市
  431. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  432. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  433. Buyaverageprice float64 `json:"buyaverageprice" xorm:"-"` // 持仓均价
  434. }
  435. // GetHsbyMyGoods 获取“我的商品”信息
  436. // 输入 accountIDs string 资金账户列表,格式 1,2,3
  437. // 输出 []HsbyMyGoods “我的商品”信息
  438. // 输入 error error
  439. func GetHsbyMyGoods(accountIDs string) ([]HsbyMyGoods, error) {
  440. engine := db.GetEngine()
  441. hsbyMyGoodses := make([]HsbyMyGoods, 0)
  442. // 此定制版本,只查询出当前手数(期末)大于0的数据 (TRADEPOSITION.BUYCURPOSITIONQTY > 0)
  443. if err := engine.Table("TRADEPOSITION").
  444. Select(`TRADEPOSITION.*, (TRADEPOSITION.BUYCURPOSITIONQTY - TRADEPOSITION.BUYFROZENQTY - TRADEPOSITION.BUYOTHERFROZENQTY) ENABLEQTY,
  445. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT, GOODS.GOODSSTATUS,
  446. HSBY_GOODSEX.PICURLS,
  447. ENUMDICITEM.PARAM2 CURRENCYSIGN`).
  448. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADEPOSITION.GOODSID").
  449. Join("INNER", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  450. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  451. Where(fmt.Sprintf("TRADEPOSITION.BUYCURPOSITIONQTY > 0 and TRADEPOSITION.ACCOUNTID in (%s)", accountIDs)).Find(&hsbyMyGoodses); err != nil {
  452. return nil, err
  453. }
  454. for i := range hsbyMyGoodses {
  455. myGoods := &hsbyMyGoodses[i]
  456. // 持仓均价
  457. averagePrice := myGoods.Buycurholderamount / float64(myGoods.Buycurpositionqty) / myGoods.Agreeunit
  458. myGoods.Buyaverageprice, _ = strconv.ParseFloat(utils.FormatFloat(averagePrice, int(myGoods.Decimalplace)), 64)
  459. }
  460. return hsbyMyGoodses, nil
  461. }
  462. // HsbyPreGoods 新品上市商品(一级市场产能预售)
  463. type HsbyPreGoods struct {
  464. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID(自增ID SEQ_GOODS)
  465. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  466. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  467. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  468. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 所属市场ID
  469. Goodsstatus int64 `json:"goodsstatus" xorm:"'GOODSSTATUS'"` // 商品状态- 2:未上市 3:上市
  470. Quoteminunit int64 `json:"quoteminunit" xorm:"'QUOTEMINUNIT'"` // 行情最小变动单位 [整数,报价小数位一起使用]
  471. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  472. Listingdate time.Time `json:"listingdate" xorm:"'LISTINGDATE'"` // 交易开始日期
  473. Lasttradedate time.Time `json:"lasttradedate" xorm:"'LASTTRADEDATE'"` // 最后交易日期(状态:待退市)
  474. Relatedgoodsid int64 `json:"relatedgoodsid" xorm:"'RELATEDGOODSID'"` // 关联交易合约ID
  475. Presaleqty int64 `json:"presaleqty" xorm:"'PRESALEQTY'"` // 预售数量
  476. Refprice float64 `json:"refprice" xorm:"'REFPRICE'"` // 参考价格[一口价]
  477. Presaledqty int64 `json:"presaledqty" xorm:"'PRESALEDQTY'"` // 已预售量(预售结束时更新)
  478. EnableQty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 剩余数量
  479. Currency string `json:"currency" xorm:"'CURRENCY'"` // 货币
  480. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  481. Videourls string `json:"videourls" xorm:"'VIDEOURLS'"` // 介绍视频[多张用逗号分隔]
  482. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  483. Trademode int32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  484. }
  485. // GetHsbyPreGoodses 获取“新品上市”商品列表(一级市场产能预售)
  486. // 输入 marketIDs string 市场ID列表,格式 1,2,3
  487. // 输入 descProvinceID int 省ID
  488. // 输入 descCityID int 市ID
  489. // 输出 []HsbyPreGoods “新品上市”商品列表
  490. // 输出 error error
  491. func GetHsbyPreGoodses(marketIDs string, descProvinceID, descCityID int) ([]HsbyPreGoods, error) {
  492. engine := db.GetEngine()
  493. // 注意:一级产能预售市场使用的商品实际上是和二级市场有关系的,所以要使用 CPTRADE_PRESALEGOODSEX.RELATEDGOODSID 进行关联
  494. // 注意:CPTRADE_PRESALEGOODSEX 表的开始与结束时间是给大宗用的
  495. preGoodses := make([]HsbyPreGoods, 0)
  496. session := engine.Table("GOODS").
  497. Select(`GOODS.*,
  498. CPTRADE_PRESALEGOODSEX.RELATEDGOODSID, CPTRADE_PRESALEGOODSEX.PRESALEQTY, CPTRADE_PRESALEGOODSEX.REFPRICE,
  499. CPTRADE_PRESALEGOODSEX.PRESALEDQTY, (CPTRADE_PRESALEGOODSEX.PRESALEQTY - CPTRADE_PRESALEGOODSEX.PRESALEDQTY) ENABLEQTY,
  500. ENUMDICITEM.ENUMDICNAME CURRENCY, ENUMDICITEM.PARAM2 CURRENCYSIGN,
  501. HSBY_GOODSEX.VIDEOURLS, HSBY_GOODSEX.PICURLS,
  502. MARKET.TRADEMODE`).
  503. Join("INNER", "CPTRADE_PRESALEGOODSEX", "CPTRADE_PRESALEGOODSEX.GOODSID = GOODS.GOODSID").
  504. Join("LEFT", "ENUMDICITEM", "ENUMDICITEM.ENUMITEMNAME = GOODS.CURRENCYID and ENUMDICITEM.ENUMDICCODE = 'currency'").
  505. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = CPTRADE_PRESALEGOODSEX.RELATEDGOODSID").
  506. Join("LEFT", "MARKET", "MARKET.MARKETID = GOODS.MARKETID").
  507. Where(fmt.Sprintf("GOODS.GOODSSTATUS in (2,3) and GOODS.MARKETID in (%s)", marketIDs)) // 一级市场获取 2:未上市 3:上市 状态的商品
  508. if descProvinceID > 0 {
  509. session = session.And("HSBY_GOODSEX.DESCPROVINCEID = ?", descProvinceID)
  510. }
  511. if descCityID > 0 {
  512. session = session.And("HSBY_GOODSEX.DESCCITYID = ?", descCityID)
  513. }
  514. if err := session.Find(&preGoodses); err != nil {
  515. return nil, err
  516. }
  517. // for i := range preGoodses {
  518. // preGoods := &preGoodses[i]
  519. // // FIXME: - 这里应该使用 Duck Typing,后期再处理
  520. // // 计算最小变动单位
  521. // lotSize := float64(preGoods.Quoteminunit) * math.Pow(0.1, float64(preGoods.Decimalplace))
  522. // preGoods.LotSize, _ = strconv.ParseFloat(utils.FormatFloat(lotSize, int(preGoods.Decimalplace)), 64)
  523. // }
  524. return preGoodses, nil
  525. }
  526. // HsbyPreGoodsDetail 一级市场(产能预售)商品信息详情
  527. type HsbyPreGoodsDetail struct {
  528. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID(自增ID SEQ_GOODS)
  529. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  530. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  531. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  532. Marketid int64 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 所属市场ID
  533. Goodsstatus int64 `json:"goodsstatus" xorm:"'GOODSSTATUS'"` // 商品状态- 2:未上市 3:上市
  534. Quoteminunit int64 `json:"quoteminunit" xorm:"'QUOTEMINUNIT'"` // 行情最小变动单位 [整数,报价小数位一起使用]
  535. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  536. Listingdate time.Time `json:"listingdate" xorm:"'LISTINGDATE'"` // 交易开始日期
  537. Lasttradedate time.Time `json:"lasttradedate" xorm:"'LASTTRADEDATE'"` // 最后交易日期(状态:待退市)
  538. Relatedgoodsid int64 `json:"relatedgoodsid" xorm:"'RELATEDGOODSID'"` // 关联交易合约ID
  539. Presaleqty int64 `json:"presaleqty" xorm:"'PRESALEQTY'"` // 预售数量
  540. Refprice float64 `json:"refprice" xorm:"'REFPRICE'"` // 参考价格[一口价]
  541. Presaledqty int64 `json:"presaledqty" xorm:"'PRESALEDQTY'"` // 已预售量(预售结束时更新)
  542. EnableQty int64 `json:"enableqty" xorm:"ENABLEQTY"` // 剩余数量
  543. Videourls string `json:"videourls" xorm:"'VIDEOURLS'"` // 介绍视频[多张用逗号分隔]
  544. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  545. Descprovinceid int64 `json:"descprovinceid" xorm:"'DESCPROVINCEID'"` // 目的地(省)ID
  546. Desccityid int64 `json:"desccityid" xorm:"'DESCCITYID'"` // 目的地(市)ID
  547. Goodsdesc string `json:"goodsdesc" xorm:"'GOODSDESC'"` // 商品详情
  548. Currency string `json:"currency" xorm:"'CURRENCY'"` // 货币
  549. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  550. Goodunit string `json:"goodunit" xorm:"GOODUNIT"` // 报价单位
  551. Vendorname string `json:"vendorname" xorm:"'VENDORNAME'"` // 供应商名称
  552. Vendorphone string `json:"vendorphone" xorm:"'VENDORPHONE'"` // 供应商客服电话
  553. Vendorattr string `json:"vendorattr" xorm:"'VENDORATTR'"` // 供应商附件(多张,逗号分隔)
  554. Trademode int32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  555. Customername string `json:"customername" xorm:"'CUSTOMERNAME'"` // 发行单位
  556. StepValue float64 `json:"stepvalue" xorm:"-"` // 价格最小变动单位
  557. LotSize int `json:"lotsize" xorm:"-"` // 手数最小变动单位
  558. Buymaxqty int `json:"buymaxqty" xorm:"'-'"` // 购买上限 [71] - 0为不限
  559. }
  560. // GetHsbyPreGoodsDetail 获取一级市场(产能预售)商品信息详情
  561. // 参数 goodsID int 目标商品ID
  562. // 返回 *HsbyListingGoodsDetail 二级市场(挂牌点选)商品信息详情,查询无结果返回nil
  563. // 返回 error error
  564. func GetHsbyPreGoodsDetail(goodsID, accountID int) (*HsbyPreGoodsDetail, error) {
  565. engine := db.GetEngine()
  566. details := make([]HsbyPreGoodsDetail, 0)
  567. // 获取挂牌商品信息,以及扩展表信息
  568. // FIXME: - 这里使用Get方法,会造成SQL语句的嵌套出错,后期再研究
  569. session := engine.Table("GOODS").
  570. Select(`GOODS.*,
  571. CPTRADE_PRESALEGOODSEX.RELATEDGOODSID, CPTRADE_PRESALEGOODSEX.PRESALEQTY, CPTRADE_PRESALEGOODSEX.REFPRICE,
  572. CPTRADE_PRESALEGOODSEX.PRESALEDQTY, (CPTRADE_PRESALEGOODSEX.PRESALEQTY - CPTRADE_PRESALEGOODSEX.PRESALEDQTY) ENABLEQTY,
  573. HSBY_GOODSEX.VIDEOURLS, HSBY_GOODSEX.PICURLS, HSBY_GOODSEX.DESCPROVINCEID, HSBY_GOODSEX.Desccityid, HSBY_GOODSEX.Goodsdesc,
  574. ENUMDICITEM.ENUMDICNAME CURRENCY, ENUMDICITEM.PARAM2 CURRENCYSIGN,
  575. E1.ENUMDICNAME GOODUNIT,
  576. HSBY_SUPPLIERINFO.VENDORNAME, HSBY_SUPPLIERINFO.VENDORPHONE, HSBY_SUPPLIERINFO.VENDORATTR,
  577. MARKET.TRADEMODE,
  578. USERINFO.CUSTOMERNAME`).
  579. Join("INNER", "CPTRADE_PRESALEGOODSEX", "CPTRADE_PRESALEGOODSEX.GOODSID = GOODS.GOODSID").
  580. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = CPTRADE_PRESALEGOODSEX.RELATEDGOODSID").
  581. Join("LEFT", "ENUMDICITEM", "ENUMDICITEM.ENUMITEMNAME = GOODS.CURRENCYID and ENUMDICITEM.ENUMDICCODE = 'currency'").
  582. Join("LEFT", "ENUMDICITEM E1", "E1.ENUMITEMNAME = GOODS.GOODUNITID and E1.ENUMDICCODE = 'goodsunit'").
  583. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  584. Join("LEFT", "MARKET", "MARKET.MARKETID = GOODS.MARKETID").
  585. Join("LEFT", "USERINFO", "USERINFO.USERID = CPTRADE_PRESALEGOODSEX.USERID").
  586. Where("GOODS.GOODSID = ?", goodsID)
  587. if err := session.Find(&details); err != nil {
  588. return nil, err
  589. }
  590. // 无目标商品
  591. if len(details) == 0 {
  592. return nil, nil
  593. }
  594. preGoodsDetail := details[0]
  595. // FIXME: - 这里应该使用 Duck Typing,后期再处理
  596. // 计算价格最小变动单位
  597. stepValue := float64(preGoodsDetail.Quoteminunit) * math.Pow(0.1, float64(preGoodsDetail.Decimalplace))
  598. preGoodsDetail.StepValue, _ = strconv.ParseFloat(utils.FormatFloat(stepValue, int(preGoodsDetail.Decimalplace)), 64)
  599. // 计算手数最小变动单位,一级市场固定为1
  600. preGoodsDetail.LotSize = 1
  601. // 获取购买上限
  602. buyMaxQty, err := GetCPTradeBuyLimit(goodsID, accountID)
  603. if err != nil {
  604. return nil, err
  605. }
  606. preGoodsDetail.Buymaxqty = buyMaxQty
  607. return &preGoodsDetail, nil
  608. }
  609. // HsbySellMyDetail "我的闲置"单据信息(已发布 - 二级市场卖挂,3:委托成功、7:部分成交; 已完成 - 二级市场成交单,包括历史数据)
  610. type HsbySellMyDetail struct {
  611. Orderid string `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 单号(已发布 - 委托单号;已完成 - 成交单号)
  612. Marketid int32 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID
  613. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID
  614. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
  615. Buyorsell int32 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  616. Price float64 `json:"price" xorm:"'PRICE'"` // 价格
  617. Qty int64 `json:"qty" xorm:"'QTY'" binding:"required"` // 数量
  618. Time time.Time `json:"time" xorm:"'TIME'" binding:"required"` // 时间
  619. Amount float64 `json:"amount" xorm:"'AMOUNT'"` // 金额 = 价格 * 数量 * 合约单位
  620. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  621. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  622. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  623. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  624. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  625. Trademode uint32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  626. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  627. Vendorname string `json:"vendorname" xorm:"'VENDORNAME'"` // 供应商名称
  628. OrderType int32 `json:"ordertype" xorm:"'ORDERTYPE'"` // 单据类型:0 - 已发布, 1 - 已完成
  629. }
  630. // GetHsbySellMyOrderDetails 获取"我的闲置 - 已发布"单据信息
  631. // 输入 accountIDs string 资金账户列表
  632. // 输出 []HsbySellMyDetail "我的闲置 - 已发布"单据信息
  633. // 输出 error error
  634. func GetHsbySellMyOrderDetails(accountIDs string) ([]HsbySellMyDetail, error) {
  635. // 获取市场信息
  636. markets, err := GetMarkets()
  637. if err != nil {
  638. return nil, err
  639. }
  640. engine := db.GetEngine()
  641. marketIDs := "" // 我的闲置-已发布: 二级市场卖挂牌
  642. // 默认取 TradeMode = 16
  643. for _, v := range markets {
  644. if v.Trademode == 16 {
  645. if len(marketIDs) == 0 {
  646. marketIDs = strconv.Itoa(int(v.Marketid))
  647. } else {
  648. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  649. }
  650. }
  651. }
  652. orderDetails := make([]HsbySellMyDetail, 0)
  653. // “我的闲置 - 已发布”都是卖挂委托
  654. session := engine.Table("TRADE_ORDERDETAIL").
  655. Select(`to_char(TRADE_ORDERDETAIL.ORDERID) ORDERID,
  656. TRADE_ORDERDETAIL.MARKETID, TRADE_ORDERDETAIL.GOODSID, TRADE_ORDERDETAIL.ACCOUNTID, TRADE_ORDERDETAIL.BUYORSELL,
  657. TRADE_ORDERDETAIL.ORDERPRICE PRICE, TRADE_ORDERDETAIL.ORDERQTY QTY, TRADE_ORDERDETAIL.ORDERTIME TIME,
  658. (TRADE_ORDERDETAIL.ORDERPRICE * TRADE_ORDERDETAIL.ORDERQTY * GOODS.AGREEUNIT) AMOUNT,
  659. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  660. HSBY_GOODSEX.PICURLS,
  661. MARKET.TRADEMODE,
  662. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  663. HSBY_SUPPLIERINFO.VENDORNAME,
  664. 0 ORDERTYPE`).
  665. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_ORDERDETAIL.GOODSID").
  666. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  667. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  668. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_ORDERDETAIL.MARKETID").
  669. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  670. Where(fmt.Sprintf(`TRADE_ORDERDETAIL.BUYORSELL = 1 and TRADE_ORDERDETAIL.LISTINGSELECTTYPE = 1 and (TRADE_ORDERDETAIL.ORDERSTATUS = 3 or TRADE_ORDERDETAIL.ORDERSTATUS = 7)
  671. and TRADE_ORDERDETAIL.ACCOUNTID in (%s)`, accountIDs)).
  672. And(fmt.Sprintf("TRADE_ORDERDETAIL.MARKETID in (%s)", marketIDs))
  673. if err := session.Find(&orderDetails); err != nil {
  674. return nil, err
  675. }
  676. return orderDetails, nil
  677. }
  678. // GetHsbySellMyTradeDetails 获取"我的闲置 - 已完成"单据信息
  679. // 输入 accountIDs string 资金账户列表
  680. // 输出 []HsbySellMyDetail "我的闲置 - 已完成"单据信息
  681. // 输出 error error
  682. func GetHsbySellMyTradeDetails(accountIDs string) ([]HsbySellMyDetail, error) {
  683. // 获取市场信息
  684. markets, err := GetMarkets()
  685. if err != nil {
  686. return nil, err
  687. }
  688. engine := db.GetEngine()
  689. marketIDs := "" // 我的闲置-已发布: 二级市场卖方向成交单(包括历史成交单)
  690. // 默认取 TradeMode = 16
  691. for _, v := range markets {
  692. if v.Trademode == 16 {
  693. if len(marketIDs) == 0 {
  694. marketIDs = strconv.Itoa(int(v.Marketid))
  695. } else {
  696. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  697. }
  698. }
  699. }
  700. orders := make([]HsbySellMyDetail, 0)
  701. // 当前成交单
  702. curOrders := make([]HsbySellMyDetail, 0)
  703. if err := engine.Table("TRADE_TRADEDETAIL").
  704. Select(`to_char(TRADE_TRADEDETAIL.TRADEID) ORDERID,
  705. TRADE_TRADEDETAIL.MARKETID, TRADE_TRADEDETAIL.GOODSID, TRADE_TRADEDETAIL.ACCOUNTID, TRADE_TRADEDETAIL.BUYORSELL,
  706. TRADE_TRADEDETAIL.TRADEPRICE PRICE, TRADE_TRADEDETAIL.TRADEQTY QTY, TRADE_TRADEDETAIL.TRADETIME TIME, TRADE_TRADEDETAIL.TRADEAMOUNT AMOUNT,
  707. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  708. HSBY_GOODSEX.PICURLS,
  709. MARKET.TRADEMODE,
  710. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  711. HSBY_SUPPLIERINFO.VENDORNAME,
  712. 1 ORDERTYPE`).
  713. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_TRADEDETAIL.GOODSID").
  714. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  715. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  716. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_TRADEDETAIL.MARKETID").
  717. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  718. Where(fmt.Sprintf(`TRADE_TRADEDETAIL.BUYORSELL = 1
  719. and TRADE_TRADEDETAIL.ACCOUNTID in (%s)`, accountIDs)).
  720. And(fmt.Sprintf("TRADE_TRADEDETAIL.MARKETID in (%s)", marketIDs)).Find(&curOrders); err != nil {
  721. return nil, err
  722. }
  723. if len(curOrders) > 0 {
  724. orders = append(orders, curOrders...)
  725. }
  726. // 历史成交单
  727. hisOrders := make([]HsbySellMyDetail, 0)
  728. if err := engine.Table("HIS_TRADE_TRADEDETAIL").
  729. Select(`to_char(HIS_TRADE_TRADEDETAIL.TRADEID) ORDERID,
  730. HIS_TRADE_TRADEDETAIL.MARKETID, HIS_TRADE_TRADEDETAIL.GOODSID, HIS_TRADE_TRADEDETAIL.ACCOUNTID, HIS_TRADE_TRADEDETAIL.BUYORSELL,
  731. HIS_TRADE_TRADEDETAIL.TRADEPRICE PRICE, HIS_TRADE_TRADEDETAIL.TRADEQTY QTY, HIS_TRADE_TRADEDETAIL.TRADETIME TIME, HIS_TRADE_TRADEDETAIL.TRADEAMOUNT AMOUNT,
  732. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  733. HSBY_GOODSEX.PICURLS,
  734. MARKET.TRADEMODE,
  735. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  736. HSBY_SUPPLIERINFO.VENDORNAME,
  737. 1 ORDERTYPE`).
  738. Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_TRADEDETAIL.GOODSID").
  739. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  740. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  741. Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_TRADEDETAIL.MARKETID").
  742. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  743. Where(fmt.Sprintf(`HIS_TRADE_TRADEDETAIL.BUYORSELL = 1 and HIS_TRADE_TRADEDETAIL.ISVALIDDATA = 1
  744. and HIS_TRADE_TRADEDETAIL.ACCOUNTID in (%s)`, accountIDs)).
  745. And(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.MARKETID in (%s)", marketIDs)).Find(&hisOrders); err != nil {
  746. return nil, err
  747. }
  748. if len(hisOrders) > 0 {
  749. orders = append(orders, hisOrders...)
  750. }
  751. return orders, nil
  752. }
  753. // HsbyMyPackage 我的包裹信息
  754. type HsbyMyPackage struct {
  755. Takeorderid string `json:"takeorderid" xorm:"'TAKEORDERID'" binding:"required"` // 提货单号(905+Unix秒时间戳(10位)+xxxxxx)
  756. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'"` // 账户ID
  757. Goodsid int64 `json:"goodsid" xorm:"'GOODSID'"` // 商品ID
  758. Userid int64 `json:"userid" xorm:"'USERID'"` // 用户ID
  759. Qty float64 `json:"qty" xorm:"'QTY'"` // 提货数量
  760. Reqtime time.Time `json:"reqtime" xorm:"'REQTIME'"` // 更新时间
  761. Recivername string `json:"recivername" xorm:"'RECIVERNAME'"` // 提货人姓名
  762. Cardtypeid int32 `json:"cardtypeid" xorm:"'CARDTYPEID'"` // 提货人证件类型
  763. Cardnum string `json:"cardnum" xorm:"'CARDNUM'"` // 提货人证件号码
  764. Phonenum string `json:"phonenum" xorm:"'PHONENUM'"` // 提货人联系方式
  765. Takemode int32 `json:"takemode" xorm:"'TAKEMODE'"` // 提货方式 - 2:自提 3:配送
  766. Address string `json:"address" xorm:"'ADDRESS'"` // 提货人详细地址
  767. Takeremark string `json:"takeremark" xorm:"'TAKEREMARK'"` // 提货备注
  768. Takeorderstatus int32 `json:"takeorderstatus" xorm:"'TAKEORDERSTATUS'"` // 提货状态 - 1:待发货 2:已发货 3:已收货
  769. Auditer int32 `json:"auditer" xorm:"'AUDITER'"` // 审核人
  770. Audittime time.Time `json:"audittime" xorm:"'AUDITTIME'"` // 审核时间
  771. Checkremark string `json:"checkremark" xorm:"'CHECKREMARK'"` // 审核备注
  772. Tradedate string `json:"tradedate" xorm:"'TRADEDATE'"` // 交易日(yyyyMMdd)
  773. Marketid int32 `json:"marketid" xorm:"'MARKETID'"` // 市场ID
  774. Handlestatus int32 `json:"handlestatus" xorm:"'HANDLESTATUS'"` // 处理状态
  775. Amount float64 `json:"amount" xorm:"'AMOUNT'"` // 提货金额
  776. Averageprice float64 `json:"averageprice" xorm:"'AVERAGEPRICE'"` // 均价
  777. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  778. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  779. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  780. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  781. Picurls string `json:"picurls" xorm:"'PICURLS'"` // 介绍图片[多张用逗号分隔]
  782. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  783. Vendorname string `json:"vendorname" xorm:"'VENDORNAME'"` // 供应商名称
  784. }
  785. // GetHsbyMyPackages 获取我的包裹信息
  786. // 输入 accountIDs string 资金账户列表
  787. // 输入 takeOrderStatus int 提货状态 - 1:待发货 2:已发货 3:已收货
  788. // 输出 []HsbyMyPackage 我的包裹信息
  789. // 输出 error error
  790. func GetHsbyMyPackages(accountIDs string, takeOrderStatus int) ([]HsbyMyPackage, error) {
  791. engine := db.GetEngine()
  792. myPackages := make([]HsbyMyPackage, 0)
  793. session := engine.Table("TRADE_GOODSPICKUP").
  794. Select(`to_char(TRADE_GOODSPICKUP.TAKEORDERID) TAKEORDERID, (DIVISION.PATHNAME || TRADE_GOODSPICKUP.ADDRESS) ADDRESS, TRADE_GOODSPICKUP.*,
  795. (TRADE_GOODSPICKUP.AMOUNT/TRADE_GOODSPICKUP.QTY/GOODS.AGREEUNIT) AVERAGEPRICE,
  796. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  797. HSBY_GOODSEX.PICURLS,
  798. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  799. HSBY_SUPPLIERINFO.VENDORNAME`).
  800. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_GOODSPICKUP.GOODSID").
  801. Join("LEFT", "HSBY_GOODSEX", "HSBY_GOODSEX.GOODSID = GOODS.GOODSID").
  802. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  803. Join("LEFT", "HSBY_SUPPLIERINFO", "HSBY_SUPPLIERINFO.VENDORID = HSBY_GOODSEX.VENDORID").
  804. Join("LEFT", "DIVISION", "DIVISION.AUTOID = TRADE_GOODSPICKUP.DISTRICTID").
  805. Where(fmt.Sprintf("TRADE_GOODSPICKUP.ACCOUNTID in (%s)", accountIDs))
  806. if takeOrderStatus > 0 {
  807. session = session.And("TAKEORDERSTATUS = ?", takeOrderStatus)
  808. }
  809. if err := session.Find(&myPackages); err != nil {
  810. return nil, err
  811. }
  812. // FIXME:- 目前暂时在服务端对手机号码进行解密
  813. key, _ := hex.DecodeString(utils.AESSecretKey)
  814. for i := range myPackages {
  815. myPackage := &myPackages[i]
  816. // 解密手机号码
  817. if phonenum, err := hex.DecodeString(myPackage.Phonenum); err == nil { // hex -> []byte
  818. if mobile, err := utils.AESDecrypt(phonenum, key); err == nil {
  819. myPackage.Phonenum = string(mobile)
  820. }
  821. }
  822. }
  823. return myPackages, nil
  824. }
  825. // SetHsbyMyPackagesStatus 设置我的包裹提货状态
  826. func SetHsbyMyPackagesStatus(takeOrderID string, accountID, status int) error {
  827. engine := db.GetEngine()
  828. sql := fmt.Sprintf("update TRADE_GOODSPICKUP set TAKEORDERSTATUS = %d where TAKEORDERID = %s and ACCOUNTID = %d", status, takeOrderID, accountID)
  829. _, err := engine.Exec(sql)
  830. return err
  831. }
  832. // GetHsbyProvincesAndCities 获取省市信息数组
  833. // 参数 provinceID int 省ID,选填
  834. // 返回 []Division 枚举信息数组
  835. // 返回 error error
  836. func GetHsbyProvincesAndCities(provinceID int) ([]Division, error) {
  837. engine := db.GetEngine()
  838. divisions := make([]Division, 0)
  839. session := engine.Where("DIVISIONLEVEL = 'province' or DIVISIONLEVEL = 'city'").
  840. And(`AUTOID in (
  841. (select DESCPROVINCEID AUTOID from HSBY_GOODSEX inner join GOODS on GOODS.GOODSID = HSBY_GOODSEX.GOODSID and GOODS.GOODSSTATUS in (2,3))
  842. union all
  843. (select DESCCITYID AUTOID from HSBY_GOODSEX inner join GOODS on GOODS.GOODSID = HSBY_GOODSEX.GOODSID and GOODS.GOODSSTATUS in (2,3))
  844. )`)
  845. if provinceID > 0 {
  846. session = session.And("AUTOID = ?", provinceID)
  847. }
  848. if err := session.Find(&divisions); err != nil {
  849. return nil, err
  850. }
  851. return divisions, nil
  852. }
  853. // HsbyBuyMyTradeDetail "我的订单 - 已完成"单据信息(一二级市场成交单,包括历史数据)
  854. type HsbyBuyMyTradeDetail struct {
  855. Orderid string `json:"orderid" xorm:"'ORDERID'" binding:"required"` // 单号(成交单号)
  856. Marketid int32 `json:"marketid" xorm:"'MARKETID'" binding:"required"` // 市场ID
  857. Goodsid int32 `json:"goodsid" xorm:"'GOODSID'" binding:"required"` // 商品ID
  858. Accountid int64 `json:"accountid" xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
  859. Buyorsell int32 `json:"buyorsell" xorm:"'BUYORSELL'" binding:"required"` // 买卖 - 0:买 1:卖
  860. Price float64 `json:"price" xorm:"'PRICE'"` // 价格
  861. Qty int64 `json:"qty" xorm:"'QTY'" binding:"required"` // 数量
  862. Time time.Time `json:"time" xorm:"'TIME'" binding:"required"` // 时间
  863. Amount float64 `json:"amount" xorm:"'AMOUNT'"` // 金额 = 价格 * 数量 * 合约单位
  864. Goodscode string `json:"goodscode" xorm:"'GOODSCODE'" binding:"required"` // 商品代码(内部)
  865. Goodsname string `json:"goodsname" xorm:"'GOODSNAME'" binding:"required"` // 商品名称
  866. Decimalplace int64 `json:"decimalplace" xorm:"'DECIMALPLACE'"` // 报价小数位
  867. Agreeunit float64 `json:"agreeunit" xorm:"'AGREEUNIT'"` // 合约单位
  868. Picurls1 string `json:"picurls1" xorm:"'PICURLS1'"` // 预售商品介绍图片[多张用逗号分隔]
  869. Picurls2 string `json:"picurls2" xorm:"'PICURLS2'"` // 挂牌商品介绍图片[多张用逗号分隔]
  870. Trademode uint32 `json:"trademode" xorm:"'TRADEMODE'" binding:"required"` // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
  871. Currencysign string `json:"currencysign" xorm:"'CURRENCYSIGN'"` // 货币符号
  872. Vendorname1 string `json:"vendorname1" xorm:"'VENDORNAME1'"` // 预售商品供应商名称
  873. Vendorname2 string `json:"vendorname2" xorm:"'VENDORNAME2'"` // 挂牌商品供应商名称
  874. }
  875. // GetHsbyBuyMyTradeDetails 获取"我的订单 - 已完成"单据信息(一二级市场成交单,包括历史数据)
  876. // 输入 accountIDs string 资金账户列表
  877. // 输出 []HsbyBuyMyTradeDetail "我的订单 - 已完成"单据信息
  878. // 输出 error error
  879. func GetHsbyBuyMyTradeDetails(accountIDs string) ([]HsbyBuyMyTradeDetail, error) {
  880. // 获取市场信息
  881. markets, err := GetMarkets()
  882. if err != nil {
  883. return nil, err
  884. }
  885. engine := db.GetEngine()
  886. marketIDs := "" // 我的订单包括一二级市场卖方向成交单(包括历史成交单)
  887. // 默认取 TradeMode = 16
  888. for _, v := range markets {
  889. if v.Trademode == 16 || v.Trademode == 71 {
  890. if len(marketIDs) == 0 {
  891. marketIDs = strconv.Itoa(int(v.Marketid))
  892. } else {
  893. marketIDs += "," + strconv.Itoa(int(v.Marketid))
  894. }
  895. }
  896. }
  897. orders := make([]HsbyBuyMyTradeDetail, 0)
  898. // 当前成交单
  899. curOrders := make([]HsbyBuyMyTradeDetail, 0)
  900. if err := engine.Table("TRADE_TRADEDETAIL").
  901. Select(`to_char(TRADE_TRADEDETAIL.TRADEID) ORDERID,
  902. TRADE_TRADEDETAIL.MARKETID, TRADE_TRADEDETAIL.GOODSID, TRADE_TRADEDETAIL.ACCOUNTID, TRADE_TRADEDETAIL.BUYORSELL,
  903. TRADE_TRADEDETAIL.TRADEPRICE PRICE, TRADE_TRADEDETAIL.TRADEQTY QTY, TRADE_TRADEDETAIL.TRADETIME TIME, TRADE_TRADEDETAIL.TRADEAMOUNT AMOUNT,
  904. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  905. HG1.PICURLS PICURLS1, HG2.PICURLS PICURLS2,
  906. MARKET.TRADEMODE,
  907. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  908. HS1.VENDORNAME VENDORNAME1, HS2.VENDORNAME VENDORNAME2`).
  909. Join("LEFT", "GOODS", "GOODS.GOODSID = TRADE_TRADEDETAIL.GOODSID").
  910. Join("LEFT", "CPTRADE_PRESALEGOODSEX", "CPTRADE_PRESALEGOODSEX.GOODSID = TRADE_TRADEDETAIL.GOODSID").
  911. Join("LEFT", "HSBY_GOODSEX HG1", "HG1.GOODSID = CPTRADE_PRESALEGOODSEX.RELATEDGOODSID").
  912. Join("LEFT", "HSBY_GOODSEX HG2", "HG2.GOODSID = GOODS.GOODSID").
  913. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  914. Join("LEFT", "MARKET", "MARKET.MARKETID = TRADE_TRADEDETAIL.MARKETID").
  915. Join("LEFT", "HSBY_SUPPLIERINFO HS1", "HS1.VENDORID = HG1.VENDORID").
  916. Join("LEFT", "HSBY_SUPPLIERINFO HS2", "HS2.VENDORID = HG2.VENDORID").
  917. Where(fmt.Sprintf(`TRADE_TRADEDETAIL.BUYORSELL = 0
  918. and TRADE_TRADEDETAIL.ACCOUNTID in (%s)`, accountIDs)).
  919. And(fmt.Sprintf("TRADE_TRADEDETAIL.MARKETID in (%s)", marketIDs)).Find(&curOrders); err != nil {
  920. return nil, err
  921. }
  922. if len(curOrders) > 0 {
  923. orders = append(orders, curOrders...)
  924. }
  925. // 历史成交单
  926. hisOrders := make([]HsbyBuyMyTradeDetail, 0)
  927. if err := engine.Table("HIS_TRADE_TRADEDETAIL").
  928. Select(`to_char(HIS_TRADE_TRADEDETAIL.TRADEID) ORDERID,
  929. HIS_TRADE_TRADEDETAIL.MARKETID, HIS_TRADE_TRADEDETAIL.GOODSID, HIS_TRADE_TRADEDETAIL.ACCOUNTID, HIS_TRADE_TRADEDETAIL.BUYORSELL,
  930. HIS_TRADE_TRADEDETAIL.TRADEPRICE PRICE, HIS_TRADE_TRADEDETAIL.TRADEQTY QTY, HIS_TRADE_TRADEDETAIL.TRADETIME TIME, HIS_TRADE_TRADEDETAIL.TRADEAMOUNT AMOUNT,
  931. GOODS.GOODSCODE, GOODS.GOODSNAME, GOODS.DECIMALPLACE, GOODS.AGREEUNIT,
  932. HG1.PICURLS PICURLS1, HG2.PICURLS PICURLS2,
  933. MARKET.TRADEMODE,
  934. ENUMDICITEM.PARAM2 CURRENCYSIGN,
  935. HS1.VENDORNAME VENDORNAME1, HS2.VENDORNAME VENDORNAME2`).
  936. Join("LEFT", "GOODS", "GOODS.GOODSID = HIS_TRADE_TRADEDETAIL.GOODSID").
  937. Join("LEFT", "CPTRADE_PRESALEGOODSEX", "CPTRADE_PRESALEGOODSEX.GOODSID = HIS_TRADE_TRADEDETAIL.GOODSID").
  938. Join("LEFT", "HSBY_GOODSEX HG1", "HG1.GOODSID = CPTRADE_PRESALEGOODSEX.RELATEDGOODSID").
  939. Join("LEFT", "HSBY_GOODSEX HG2", "HG2.GOODSID = GOODS.GOODSID").
  940. Join("LEFT", "ENUMDICITEM", "GOODS.CURRENCYID = ENUMDICITEM.ENUMITEMNAME and ENUMDICITEM.ENUMDICCODE = 'currency'").
  941. Join("LEFT", "MARKET", "MARKET.MARKETID = HIS_TRADE_TRADEDETAIL.MARKETID").
  942. Join("LEFT", "HSBY_SUPPLIERINFO HS1", "HS1.VENDORID = HG1.VENDORID").
  943. Join("LEFT", "HSBY_SUPPLIERINFO HS2", "HS2.VENDORID = HG2.VENDORID").
  944. Where(fmt.Sprintf(`HIS_TRADE_TRADEDETAIL.BUYORSELL = 0 and HIS_TRADE_TRADEDETAIL.ISVALIDDATA = 1
  945. and HIS_TRADE_TRADEDETAIL.ACCOUNTID in (%s)`, accountIDs)).
  946. And(fmt.Sprintf("HIS_TRADE_TRADEDETAIL.MARKETID in (%s)", marketIDs)).Find(&hisOrders); err != nil {
  947. return nil, err
  948. }
  949. if len(hisOrders) > 0 {
  950. orders = append(orders, hisOrders...)
  951. }
  952. return orders, nil
  953. }