diff --git a/bak.md b/bak.md index 5255563..09df30e 100644 --- a/bak.md +++ b/bak.md @@ -82,4 +82,61 @@ END $$; DO $$ BEGIN RAISE NOTICE '============ trading_records 部署完成 ============'; -END $$; \ No newline at end of file +END $$; + +---- + +open_year - 开仓时间:年 +open_month - 开仓时间:月 +open_day - 开仓时间:日 +symbol - 品种 +contract - 合约 +direction - 方向 +open_price - 开仓价格 +open_fee - 开仓手续费 +close_year - 平仓时间:年 +close_month - 平仓时间:月 +close_day - 平仓时间:日 +close_price - 平仓价格 +close_fee - 平仓手续费 +price_diff - 平仓差价 +min_tick - 品种最小跳点 +tick_price - 跳点价格 +diff_pnl - 差价盈亏 +total_fee - 手续费合计 +close_pnl - 平仓盈亏 + +这个文件是一份模板文件,我的SQL语句是: +CREATE TABLE trading_records ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- id + event_type VARCHAR(40) NOT NULL, -- 事件名称 + payload JSONB NOT NULL, -- 数据 + deleted BOOLEAN NOT NULL DEFAULT FALSE, -- 删除状态 + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 记录创建时间 + updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP -- 记录修改时间 + ); + +其中payload的字段为: +{ +open_year - 开仓时间:年 +open_month - 开仓时间:月 +open_day - 开仓时间:日 +symbol - 品种 +contract - 合约 +direction - 方向 +open_price - 开仓价格 +open_fee - 开仓手续费 +close_year - 平仓时间:年 +close_month - 平仓时间:月 +close_day - 平仓时间:日 +close_price - 平仓价格 +close_fee - 平仓手续费 +price_diff - 平仓差价 +min_tick - 品种最小跳点 +tick_price - 跳点价格 +diff_pnl - 差价盈亏 +total_fee - 手续费合计 +close_pnl - 平仓盈亏 +} + +你的任务是按照上传的文件的样式,帮我调整新增的业务逻辑。 \ No newline at end of file diff --git a/services/cn_futures_trading_records/src/crud/create.go b/services/cn_futures_trading_records/src/crud/create.go index f7c62f4..b0523f7 100644 --- a/services/cn_futures_trading_records/src/crud/create.go +++ b/services/cn_futures_trading_records/src/crud/create.go @@ -10,59 +10,76 @@ import ( "go.uber.org/zap" ) -// CreateRequest 注册请求参数结构 -type CreateRequest struct { - Name string `json:"name" binding:"required"` // 国家名称,必填 - Code string `json:"code" binding:"required"` // 国家代码,必填 - Flag string `json:"flag"` // 国旗信息,可选 +// TradingRecordsCreateRequest 交易记录创建请求参数结构 +type TradingRecordsCreateRequest struct { + EventType string `json:"event_type" binding:"required"` // 固定为 "futures_trade" + Payload struct { + OpenYear int `json:"open_year" binding:"required,min=1900,max=2100"` + OpenMonth int `json:"open_month" binding:"required,min=1,max=12"` + OpenDay int `json:"open_day" binding:"required,min=1,max=31"` + Symbol string `json:"symbol" binding:"required"` + Contract string `json:"contract" binding:"required"` + Direction string `json:"direction" binding:"required,oneof=long short"` + OpenPrice float64 `json:"open_price" binding:"required"` + OpenFee float64 `json:"open_fee" binding:"required,min=0"` + CloseYear int `json:"close_year" binding:"required,min=1900,max=2100"` + CloseMonth int `json:"close_month" binding:"required,min=1,max=12"` + CloseDay int `json:"close_day" binding:"required,min=1,max=31"` + ClosePrice float64 `json:"close_price" binding:"required"` + CloseFee float64 `json:"close_fee" binding:"required,min=0"` + PriceDiff float64 `json:"price_diff" binding:"required"` + MinTick float64 `json:"min_tick" binding:"required"` + TickPrice float64 `json:"tick_price" binding:"required"` + DiffPnL float64 `json:"diff_pnl" binding:"required"` + TotalFee float64 `json:"total_fee" binding:"required,min=0"` + ClosePnL float64 `json:"close_pnl" binding:"required"` + } `json:"payload" binding:"required"` } -// CreateResponse 注册响应结构 -type CreateResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - Data CreateData `json:"data"` +// TradingRecordsCreateResponse 创建响应结构 +type TradingRecordsCreateResponse struct { + Success bool `json:"success"` + Message string `json:"message"` + Data TradingRecordsCreateData `json:"data"` } -// CreateData 响应数据结构 -type CreateData struct { - CountryID string `json:"country_id"` +// TradingRecordsCreateData 响应数据结构 +type TradingRecordsCreateData struct { + RecordID string `json:"record_id"` } -// CreateHandler 处理创建逻辑 -func CreateHandler(c *gin.Context) { +// TradingRecordsCreateHandler 处理交易记录创建逻辑 +func TradingRecordsCreateHandler(c *gin.Context) { startTime := time.Now() - reqID := c.Request.Header.Get("X-RegisterRequest-ID") + reqID := c.Request.Header.Get("X-TradingRecordsRequest-ID") if reqID == "" { reqID = uuid.New().String() zap.L().Debug("✨ 生成新的请求ID", zap.String("req_id", reqID)) } - zap.L().Info("📥 收到国家创建请求", + zap.L().Info("📥 收到交易记录创建请求", zap.String("req_id", reqID), zap.String("path", c.Request.URL.Path), zap.String("method", c.Request.Method), ) - var req CreateRequest + var req TradingRecordsCreateRequest if err := c.ShouldBindJSON(&req); err != nil { zap.L().Warn("⚠️ 请求参数验证失败", zap.String("req_id", reqID), zap.Error(err), - zap.Any("request_body", c.Request.Body), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: false, - Message: "请求参数错误:name和code为必填项", + Message: "请求参数错误,请检查字段格式与必填项", }) return } zap.L().Debug("✅ 请求参数验证通过", zap.String("req_id", reqID), - zap.String("name", req.Name), - zap.String("code", req.Code), - zap.String("flag", req.Flag), + zap.String("event_type", req.EventType), + zap.Any("payload", req.Payload), ) // 开启数据库事务 @@ -72,7 +89,7 @@ func CreateHandler(c *gin.Context) { zap.String("req_id", reqID), zap.Error(err), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: false, Message: "系统错误,请稍后重试", }) @@ -91,195 +108,44 @@ func CreateHandler(c *gin.Context) { zap.String("req_id", reqID), zap.Any("recover", r), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: false, Message: "系统错误,请稍后重试", }) } }() - // 唯一性校验 - 国家名称(排除已删除数据) - var nameCount int + // 插入交易记录 + var recordID string err = tx.QueryRow( - "SELECT COUNT(*) FROM country_name WHERE name = $1 AND deleted = false", - req.Name, - ).Scan(&nameCount) + `INSERT INTO trading_records (event_type, payload, deleted, created_at, updated_at) + VALUES ($1, $2, FALSE, NOW(), NOW()) + RETURNING id`, + req.EventType, + req.Payload, + ).Scan(&recordID) if err != nil { tx.Rollback() - zap.L().Error("❌ 国家名称唯一性校验失败", - zap.String("req_id", reqID), - zap.String("name", req.Name), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "系统错误,校验名称失败", - }) - return - } - if nameCount > 0 { - tx.Rollback() - zap.L().Warn("⚠️ 国家名称已存在(未删除数据)", - zap.String("req_id", reqID), - zap.String("name", req.Name), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "国家名称已存在,请更换名称", - }) - return - } - - // 唯一性校验 - 国家编码(排除已删除数据) - var codeCount int - err = tx.QueryRow( - "SELECT COUNT(*) FROM country_code WHERE code = $1 AND deleted = false", - req.Code, - ).Scan(&codeCount) - if err != nil { - tx.Rollback() - zap.L().Error("❌ 国家编码唯一性校验失败", - zap.String("req_id", reqID), - zap.String("code", req.Code), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "系统错误,校验编码失败", - }) - return - } - if codeCount > 0 { - tx.Rollback() - zap.L().Warn("⚠️ 国家编码已存在(未删除数据)", - zap.String("req_id", reqID), - zap.String("code", req.Code), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "国家编码已存在,请更换编码", - }) - return - } - - // 唯一性校验 - 国旗(排除已删除数据,仅当提供了国旗参数时) - if req.Flag != "" { - var flagCount int - err = tx.QueryRow( - "SELECT COUNT(*) FROM country_flag WHERE flag = $1 AND deleted = false", - req.Flag, - ).Scan(&flagCount) - if err != nil { - tx.Rollback() - zap.L().Error("❌ 国旗唯一性校验失败", - zap.String("req_id", reqID), - zap.String("flag", req.Flag), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "系统错误,校验国旗失败", - }) - return - } - if flagCount > 0 { - tx.Rollback() - zap.L().Warn("⚠️ 国旗信息已存在(未删除数据)", - zap.String("req_id", reqID), - zap.String("flag", req.Flag), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "国旗信息已存在,请更换国旗", - }) - return - } - } - - // 1. 创建country主表记录 - var countryID string - err = tx.QueryRow("INSERT INTO country DEFAULT VALUES RETURNING id").Scan(&countryID) - if err != nil { - tx.Rollback() - zap.L().Error("❌ country表插入失败", + zap.L().Error("❌ trading_records 插入失败", zap.String("req_id", reqID), zap.Error(err), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: false, - Message: "创建国家记录失败", + Message: "保存交易记录失败", }) return } - zap.L().Debug("📝 country表插入成功", - zap.String("req_id", reqID), - zap.String("country_id", countryID), - ) - - // 2. 插入国家名称 - _, err = tx.Exec("INSERT INTO country_name (country_id, name) VALUES ($1, $2)", countryID, req.Name) - if err != nil { - tx.Rollback() - zap.L().Error("❌ country_name表插入失败", - zap.String("req_id", reqID), - zap.String("country_id", countryID), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "保存名称信息失败", - }) - return - } - - // 3. 插入国家代码 - _, err = tx.Exec("INSERT INTO country_code (country_id, code) VALUES ($1, $2)", countryID, req.Code) - if err != nil { - tx.Rollback() - zap.L().Error("❌ country_code表插入失败", - zap.String("req_id", reqID), - zap.String("country_id", countryID), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "保存代码信息失败", - }) - return - } - - // 4. 插入国旗信息(如果提供) - if req.Flag != "" { - _, err = tx.Exec("INSERT INTO country_flag (country_id, flag) VALUES ($1, $2)", countryID, req.Flag) - if err != nil { - tx.Rollback() - zap.L().Error("❌ country_flag表插入失败", - zap.String("req_id", reqID), - zap.String("country_id", countryID), - zap.Error(err), - ) - c.JSON(http.StatusOK, CreateResponse{ - Success: false, - Message: "保存国旗信息失败", - }) - return - } - zap.L().Debug("📝 country_flag表插入成功", - zap.String("req_id", reqID), - zap.String("country_id", countryID), - ) - } - // 提交事务 if err := tx.Commit(); err != nil { tx.Rollback() zap.L().Error("❌ 事务提交失败", zap.String("req_id", reqID), - zap.String("country_id", countryID), + zap.String("record_id", recordID), zap.Error(err), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: false, Message: "数据提交失败,请稍后重试", }) @@ -287,17 +153,17 @@ func CreateHandler(c *gin.Context) { } duration := time.Since(startTime) - zap.L().Info("✅ 国家创建请求处理完成", + zap.L().Info("✅ 交易记录创建请求处理完成", zap.String("req_id", reqID), - zap.String("country_id", countryID), + zap.String("record_id", recordID), zap.Duration("duration", duration), ) - c.JSON(http.StatusOK, CreateResponse{ + c.JSON(http.StatusOK, TradingRecordsCreateResponse{ Success: true, Message: "创建成功", - Data: CreateData{ - CountryID: countryID, + Data: TradingRecordsCreateData{ + RecordID: recordID, }, }) -} +} \ No newline at end of file