add
This commit is contained in:
@@ -3,10 +3,8 @@
|
||||
-- =========================================================
|
||||
\pset pager off
|
||||
\timing on
|
||||
-- 切换到目标数据库
|
||||
\c postgres;
|
||||
|
||||
-- 1 保证扩展存在(重复执行无害)
|
||||
CREATE EXTENSION IF NOT EXISTS "moddatetime" SCHEMA public;
|
||||
|
||||
DO $$
|
||||
@@ -14,7 +12,6 @@ BEGIN
|
||||
RAISE NOTICE '🚀============ cn_futures_trading_records 部署开始 ============🚀';
|
||||
END $$;
|
||||
|
||||
-- 2 建表(幂等)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
/* ---------- 公共 Payload 结构体 ---------- */
|
||||
/* ---------- 公共 Payload ---------- */
|
||||
type Payload struct {
|
||||
Status int `csv:"status" json:"status" binding:"required,min=-1,max=1"`
|
||||
OpenYear int `csv:"open_year" json:"open_year" binding:"required,min=1900,max=2200"`
|
||||
@@ -38,7 +38,19 @@ type Payload struct {
|
||||
TickPrice float64 `csv:"tick_price" json:"tick_price" binding:"required"`
|
||||
DiffPnL float64 `csv:"diff_pnl" json:"diff_pnl" binding:"required"`
|
||||
TotalFee float64 `csv:"total_fee" json:"total_fee" binding:"required,min=0"`
|
||||
ClosePnL float64 `csv:"close_pnl" json:"close_pnl" binding:"required"` // 客户端算好
|
||||
ClosePnL float64 `csv:"close_pnl" json:"close_pnl" binding:"required"`
|
||||
}
|
||||
|
||||
/* ---------- 包级常量:带 csv 标签的字段个数 ---------- */
|
||||
var payloadCSVCols int
|
||||
|
||||
func init() {
|
||||
typ := reflect.TypeOf(Payload{})
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
if _, ok := typ.Field(i).Tag.Lookup("csv"); ok {
|
||||
payloadCSVCols++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- 单条创建 ---------- */
|
||||
@@ -180,14 +192,14 @@ func CreateBatchHandler(c *gin.Context) {
|
||||
|
||||
var recordIDs []string
|
||||
for idx, row := range req.Rows {
|
||||
if len(row) != 19 { // 19 列(含 ClosePnL)
|
||||
if len(row) != payloadCSVCols { // ✅ 自动随结构体同步
|
||||
tx.Rollback()
|
||||
zap.L().Warn("⚠️ 字段数量不匹配", zap.String("req_id", reqID), zap.Int("row_index", idx), zap.Int("field_count", len(row)))
|
||||
c.JSON(http.StatusOK, TradingRecordsBatchCreateResponse{Success: false, Message: "第 " + strconv.Itoa(idx+1) + " 行字段数量不足 19 个"})
|
||||
zap.L().Warn("⚠️ 字段数量不匹配", zap.String("req_id", reqID), zap.Int("row_index", idx), zap.Int("field_count", len(row)), zap.Int("expected", payloadCSVCols))
|
||||
c.JSON(http.StatusOK, TradingRecordsBatchCreateResponse{Success: false, Message: "第 " + strconv.Itoa(idx+1) + " 行字段数量不足 " + strconv.Itoa(payloadCSVCols) + " 个"})
|
||||
return
|
||||
}
|
||||
|
||||
// 用 gocsv 一次性映射
|
||||
// 一次性映射
|
||||
var p Payload
|
||||
if err := gocsv.UnmarshalCSV(csv.NewReader(bytes.NewReader([]byte(strings.Join(row, ",")+"\n"))), &p); err != nil {
|
||||
tx.Rollback()
|
||||
|
||||
Reference in New Issue
Block a user