review code.
This commit is contained in:
@@ -86,210 +86,163 @@ func (s *Storage) AutoMigrate() error {
|
||||
}
|
||||
|
||||
// SaveStatus 保存完整状态数据(使用事务)
|
||||
func (s *Storage) SaveStatus(status *types.Status, dataHash string) error {
|
||||
func (s *Storage) SaveData(status *types.StatusData) error {
|
||||
// 验证必要字段 - AccountID是所有Upsert的共同条件
|
||||
if status.Data.Assets.AccountID == "" {
|
||||
return fmt.Errorf("账户ID不能为空")
|
||||
}
|
||||
|
||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 计算Ymd (年月日数字格式,如20260407)
|
||||
now := time.Now()
|
||||
ymd := now.Year()*10000 + int(now.Month())*100 + now.Day()
|
||||
// 计算Ymd (年月日数字格式,如20260407)
|
||||
now := time.Now()
|
||||
ymd := now.Year()*10000 + int(now.Month())*100 + now.Day()
|
||||
|
||||
// 保存资产快照 (先查询后更新/插入)
|
||||
var existingAsset models.CollectorAssets
|
||||
err := tx.Where("account_id = ? AND ymd = ?", status.Data.Assets.AccountID, ymd).First(&existingAsset).Error
|
||||
// 保存资产快照 (先查询后更新/插入)
|
||||
var existingAsset models.CollectorAssets
|
||||
err := s.db.Where("account_id = ? AND ymd = ?", status.Data.Assets.AccountID, ymd).First(&existingAsset).Error
|
||||
|
||||
asset := models.CollectorAssets{
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
Ymd: ymd,
|
||||
Cash: status.Data.Assets.Cash,
|
||||
FrozenCash: status.Data.Assets.FrozenCash,
|
||||
MarketValue: status.Data.Assets.MarketValue,
|
||||
Profit: status.Data.Assets.Profit,
|
||||
TotalAsset: status.Data.Assets.TotalAsset,
|
||||
DataHash: dataHash,
|
||||
CollectedAt: now,
|
||||
asset := models.CollectorAssets{
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
Ymd: ymd,
|
||||
Cash: status.Data.Assets.Cash,
|
||||
FrozenCash: status.Data.Assets.FrozenCash,
|
||||
MarketValue: status.Data.Assets.MarketValue,
|
||||
Profit: status.Data.Assets.Profit,
|
||||
TotalAsset: status.Data.Assets.TotalAsset,
|
||||
CollectedAt: now,
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := s.db.Create(&asset).Error; err != nil {
|
||||
return fmt.Errorf("插入资产快照失败: %w", err)
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := tx.Create(&asset).Error; err != nil {
|
||||
return fmt.Errorf("插入资产快照失败: %w", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询资产快照失败: %w", err)
|
||||
} else {
|
||||
// 记录存在,更新现有记录
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询资产快照失败: %w", err)
|
||||
} else {
|
||||
// 记录存在,更新现有记录
|
||||
if asset.Cash != existingAsset.Cash || asset.FrozenCash != existingAsset.FrozenCash || asset.MarketValue != existingAsset.MarketValue || asset.Profit != existingAsset.Profit || asset.TotalAsset != existingAsset.TotalAsset {
|
||||
asset.ID = existingAsset.ID
|
||||
if err := tx.Save(&asset).Error; err != nil {
|
||||
if err := s.db.Save(&asset).Error; err != nil {
|
||||
return fmt.Errorf("更新资产快照失败: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量保存订单 (先查询后更新/插入)
|
||||
if len(status.Data.Orders) > 0 {
|
||||
for _, order := range status.Data.Orders {
|
||||
// 验证必要条件: OrderID和StockCode
|
||||
if order.OrderID == 0 {
|
||||
continue
|
||||
}
|
||||
if order.StockCode == "" {
|
||||
continue
|
||||
}
|
||||
// 只存储成交的订单
|
||||
if order.OrderStatus != 56 {
|
||||
continue
|
||||
}
|
||||
var open_price float64
|
||||
var info types.OrderInfo
|
||||
err = json.Unmarshal([]byte(order.OrderRemark), &info)
|
||||
if err == nil {
|
||||
open_price = info.Op
|
||||
}
|
||||
// 批量保存订单 (先查询后更新/插入)
|
||||
if len(status.Data.Orders) > 0 {
|
||||
for _, order := range status.Data.Orders {
|
||||
// 验证必要条件: OrderID和StockCode
|
||||
if order.OrderID == 0 {
|
||||
continue
|
||||
}
|
||||
if order.StockCode == "" {
|
||||
continue
|
||||
}
|
||||
// 只存储成交的订单
|
||||
if order.OrderStatus != 56 {
|
||||
continue
|
||||
}
|
||||
var open_price float64
|
||||
var info types.OrderInfo
|
||||
err = json.Unmarshal([]byte(order.OrderRemark), &info)
|
||||
if err == nil {
|
||||
open_price = info.Op
|
||||
}
|
||||
|
||||
// 查询是否存在
|
||||
var existingOrder models.CollectorOrder
|
||||
err := tx.Where("account_id = ? AND order_id = ? AND ymd = ?",
|
||||
status.Data.Assets.AccountID, order.OrderID, ymd).First(&existingOrder).Error
|
||||
// 查询是否存在
|
||||
var cnt int64
|
||||
s.db.Where("account_id = ? AND order_id = ? AND ymd = ?", status.Data.Assets.AccountID, order.OrderID, ymd).Count(&cnt)
|
||||
if cnt > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
orderRecord := models.CollectorOrder{
|
||||
OrderID: order.OrderID,
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
StockCode: order.StockCode,
|
||||
Ymd: ymd,
|
||||
Price: order.Price,
|
||||
Volume: order.Volume,
|
||||
OpenPrice: open_price,
|
||||
TradedPrice: order.TradedPrice,
|
||||
TradedVolume: order.TradedVolume,
|
||||
OrderStatus: order.OrderStatus,
|
||||
OrderTime: order.OrderTime,
|
||||
OrderRemark: order.OrderRemark,
|
||||
DataHash: dataHash,
|
||||
OffsetFlag: order.OffsetFlag,
|
||||
CollectedAt: now,
|
||||
}
|
||||
orderRecord := models.CollectorOrder{
|
||||
OrderID: order.OrderID,
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
StockCode: order.StockCode,
|
||||
Ymd: ymd,
|
||||
Price: order.Price,
|
||||
Volume: order.Volume,
|
||||
OpenPrice: open_price,
|
||||
TradedPrice: order.TradedPrice,
|
||||
TradedVolume: order.TradedVolume,
|
||||
OrderStatus: order.OrderStatus,
|
||||
OrderTime: order.OrderTime,
|
||||
OrderRemark: order.OrderRemark,
|
||||
OffsetFlag: order.OffsetFlag,
|
||||
CollectedAt: now,
|
||||
CreatedAt: now,
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := tx.Create(&orderRecord).Error; err != nil {
|
||||
return fmt.Errorf("插入订单失败: %w", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询订单失败: %w", err)
|
||||
} else {
|
||||
// 记录存在,更新现有记录
|
||||
orderRecord.ID = existingOrder.ID
|
||||
if err := tx.Save(&orderRecord).Error; err != nil {
|
||||
return fmt.Errorf("更新订单失败: %w", err)
|
||||
}
|
||||
}
|
||||
// 记录不存在,插入新记录
|
||||
if err := s.db.Create(&orderRecord).Error; err != nil {
|
||||
return fmt.Errorf("插入订单失败: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量保存持仓 (先查询后更新/插入)
|
||||
if len(status.Data.Positions) > 0 {
|
||||
for _, pos := range status.Data.Positions {
|
||||
// 验证必要条件: Code
|
||||
if pos.Code == "" {
|
||||
continue
|
||||
// 批量保存持仓 (先查询后更新/插入)
|
||||
if len(status.Data.Positions) > 0 {
|
||||
for _, pos := range status.Data.Positions {
|
||||
// 验证必要条件: Code
|
||||
if pos.Code == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 查询是否存在
|
||||
var existingPosition models.CollectorPosition
|
||||
err := s.db.Where("account_id = ? AND code = ? AND ymd = ?",
|
||||
status.Data.Assets.AccountID, pos.Code, ymd).First(&existingPosition).Error
|
||||
|
||||
positionRecord := models.CollectorPosition{
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
Code: pos.Code,
|
||||
Ymd: ymd,
|
||||
Volume: pos.Volume,
|
||||
CanUseVolume: pos.CanUseVolume,
|
||||
FrozenVolume: pos.FrozenVolume,
|
||||
AvgPrice: pos.AvgPrice,
|
||||
OpenPrice: pos.OpenPrice,
|
||||
CurrentPrice: pos.CurrentPrice,
|
||||
MarketValue: pos.MarketValue,
|
||||
Profit: pos.Profit,
|
||||
ProfitRate: pos.ProfitRate,
|
||||
MinProfitRate: pos.MinProfitRate,
|
||||
CollectedAt: now,
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := s.db.Create(&positionRecord).Error; err != nil {
|
||||
return fmt.Errorf("插入持仓失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询是否存在
|
||||
var existingPosition models.CollectorPosition
|
||||
err := tx.Where("account_id = ? AND code = ? AND ymd = ?",
|
||||
status.Data.Assets.AccountID, pos.Code, ymd).First(&existingPosition).Error
|
||||
|
||||
positionRecord := models.CollectorPosition{
|
||||
AccountID: status.Data.Assets.AccountID,
|
||||
Code: pos.Code,
|
||||
Ymd: ymd,
|
||||
Volume: pos.Volume,
|
||||
CanUseVolume: pos.CanUseVolume,
|
||||
FrozenVolume: pos.FrozenVolume,
|
||||
AvgPrice: pos.AvgPrice,
|
||||
OpenPrice: pos.OpenPrice,
|
||||
CurrentPrice: pos.CurrentPrice,
|
||||
MarketValue: pos.MarketValue,
|
||||
Profit: pos.Profit,
|
||||
ProfitRate: pos.ProfitRate,
|
||||
MinProfitRate: pos.MinProfitRate,
|
||||
DataHash: dataHash,
|
||||
CollectedAt: now,
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := tx.Create(&positionRecord).Error; err != nil {
|
||||
return fmt.Errorf("插入持仓失败: %w", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询持仓失败: %w", err)
|
||||
} else {
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询持仓失败: %w", err)
|
||||
} else {
|
||||
if positionRecord.Volume != existingPosition.Volume ||
|
||||
positionRecord.CanUseVolume != existingPosition.CanUseVolume ||
|
||||
positionRecord.FrozenVolume != existingPosition.FrozenVolume ||
|
||||
positionRecord.AvgPrice != existingPosition.AvgPrice ||
|
||||
positionRecord.OpenPrice != existingPosition.OpenPrice ||
|
||||
positionRecord.CurrentPrice != existingPosition.CurrentPrice ||
|
||||
positionRecord.MarketValue != existingPosition.MarketValue ||
|
||||
positionRecord.Profit != existingPosition.Profit ||
|
||||
positionRecord.ProfitRate != existingPosition.ProfitRate {
|
||||
// 记录存在,更新现有记录
|
||||
positionRecord.ID = existingPosition.ID
|
||||
if err := tx.Save(&positionRecord).Error; err != nil {
|
||||
if err := s.db.Save(&positionRecord).Error; err != nil {
|
||||
return fmt.Errorf("更新持仓失败: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量保存行情数据 (先查询后更新/插入)
|
||||
if len(status.Data.TickData) > 0 {
|
||||
for code, tick := range status.Data.TickData {
|
||||
// 验证必要条件: StockCode
|
||||
if code == "" {
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
|
||||
// 查询是否存在
|
||||
var existingTick models.CollectorTick
|
||||
err := tx.Where("stock_code = ? AND ymd = ?", code, ymd).First(&existingTick).Error
|
||||
|
||||
tickRecord := models.CollectorTick{
|
||||
StockCode: code,
|
||||
Ymd: ymd,
|
||||
LastPrice: tick.LastPrice,
|
||||
Open: tick.Open,
|
||||
High: tick.High,
|
||||
Low: tick.Low,
|
||||
LastClose: tick.LastClose,
|
||||
Volume: tick.Volume,
|
||||
Amount: tick.Amount,
|
||||
PVolume: tick.PVolume,
|
||||
Time: tick.Time,
|
||||
TimeTag: tick.TimeTag,
|
||||
StockStatus: tick.StockStatus,
|
||||
DataHash: dataHash,
|
||||
CollectedAt: now,
|
||||
}
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,插入新记录
|
||||
if err := tx.Create(&tickRecord).Error; err != nil {
|
||||
return fmt.Errorf("插入行情数据失败: %w", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
// 查询出错
|
||||
return fmt.Errorf("查询行情数据失败: %w", err)
|
||||
} else {
|
||||
// 记录存在,更新现有记录
|
||||
tickRecord.ID = existingTick.ID
|
||||
if err := tx.Save(&tickRecord).Error; err != nil {
|
||||
return fmt.Errorf("更新行情数据失败: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// SaveCollectionLog 保存采集日志
|
||||
|
||||
Reference in New Issue
Block a user