Fix endpoints
This commit is contained in:
@ -51,9 +51,9 @@ func newController(pool *redis.Pool, userData app.UserDataProvider,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cont *Controller) GetTrades(ctx *gin.Context) {
|
func (cont *Controller) TradeCaptureReports(ctx *gin.Context) {
|
||||||
setHeaders(ctx, cont.config)
|
setHeaders(ctx, cont.config)
|
||||||
trades := cont.tradeProvider.GetTrades()
|
trades := cont.tradeProvider.TradeCaptureReports()
|
||||||
ctx.JSON(http.StatusOK, trades)
|
ctx.JSON(http.StatusOK, trades)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ func SetRoutes(api *API) {
|
|||||||
qfixpt := v1.Group("/")
|
qfixpt := v1.Group("/")
|
||||||
qfixpt.Use(cont.AuthRequired)
|
qfixpt.Use(cont.AuthRequired)
|
||||||
qfixpt.GET("/health", cont.HealthCheck)
|
qfixpt.GET("/health", cont.HealthCheck)
|
||||||
qfixpt.GET("/trades", cont.GetTrades)
|
qfixpt.GET("/trade_capture_reports", cont.TradeCaptureReports)
|
||||||
qfixpt.GET("/trades/all", cont.GetAllTrades)
|
qfixpt.GET("/trades/all", cont.GetAllTrades)
|
||||||
qfixpt.GET("/trades/:tradeID/logs", cont.GetTradeLogs)
|
qfixpt.GET("/trades/:tradeID/logs", cont.GetTradeLogs)
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,8 @@ type Config struct {
|
|||||||
|
|
||||||
// TradeProvider exposes trade data for the REST API.
|
// TradeProvider exposes trade data for the REST API.
|
||||||
type TradeProvider interface {
|
type TradeProvider interface {
|
||||||
GetTrades() []domain.PostTrade
|
TradeCaptureReports() []domain.TradeCaptureReport
|
||||||
GetAllTrades() []domain.PostTrade
|
GetAllTrades() []domain.TradeCaptureReport
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(userData app.UserDataProvider, storeInstance *store.Store, tradeProvider TradeProvider, config Config, notify domain.Notifier) *API {
|
func New(userData app.UserDataProvider, storeInstance *store.Store, tradeProvider TradeProvider, config Config, notify domain.Notifier) *API {
|
||||||
|
|||||||
@ -55,7 +55,7 @@ type Manager struct {
|
|||||||
initiator *quickfix.Initiator
|
initiator *quickfix.Initiator
|
||||||
app *application
|
app *application
|
||||||
tradesMu sync.RWMutex
|
tradesMu sync.RWMutex
|
||||||
trades map[string]*postTrade
|
trades map[string]domain.TradeCaptureReport
|
||||||
store domain.PersistenceStore
|
store domain.PersistenceStore
|
||||||
notify domain.Notifier
|
notify domain.Notifier
|
||||||
cfg app.FIXConfig
|
cfg app.FIXConfig
|
||||||
@ -63,7 +63,7 @@ type Manager struct {
|
|||||||
|
|
||||||
func NewManager(cfg app.FIXConfig, store domain.PersistenceStore, notify domain.Notifier) *Manager {
|
func NewManager(cfg app.FIXConfig, store domain.PersistenceStore, notify domain.Notifier) *Manager {
|
||||||
return &Manager{
|
return &Manager{
|
||||||
trades: make(map[string]*postTrade),
|
trades: make(map[string]domain.TradeCaptureReport),
|
||||||
store: store,
|
store: store,
|
||||||
notify: notify,
|
notify: notify,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
@ -202,7 +202,7 @@ func (m *Manager) handleTradeCaptureReport(msg tradecapturereport.TradeCaptureRe
|
|||||||
twTraderID = extractPartyByRole(s, "1007")
|
twTraderID = extractPartyByRole(s, "1007")
|
||||||
}
|
}
|
||||||
|
|
||||||
trade := domain.Trade{
|
trade := domain.TradeCaptureReport{
|
||||||
TradeReportID: tradeReportID,
|
TradeReportID: tradeReportID,
|
||||||
TradeID: tradeID,
|
TradeID: tradeID,
|
||||||
ExecID: execID,
|
ExecID: execID,
|
||||||
@ -236,43 +236,8 @@ func (m *Manager) handleTradeCaptureReport(msg tradecapturereport.TradeCaptureRe
|
|||||||
// Persist structured message.
|
// Persist structured message.
|
||||||
m.persistMessage(tradeID, parseTradeCaptureReportJSON(msg))
|
m.persistMessage(tradeID, parseTradeCaptureReportJSON(msg))
|
||||||
|
|
||||||
// Update in-memory state.
|
|
||||||
var status domain.PostTradeStatus
|
|
||||||
|
|
||||||
switch string(tradeReportType) {
|
|
||||||
case "101": // TRDCONF — trade confirmation
|
|
||||||
status = domain.PostTradeStatusActive
|
|
||||||
slog.Info("TRDCONF: trade confirmation", "tradeReportID", tradeReportID, "tradeID", tradeID)
|
|
||||||
case "102": // TRDBLOCK — block trade, log only
|
|
||||||
status = domain.PostTradeStatusActive
|
|
||||||
slog.Info("TRDBLOCK: block trade", "tradeReportID", tradeReportID, "tradeID", tradeID)
|
|
||||||
case "103": // TRDCORR — trade correction
|
|
||||||
status = domain.PostTradeStatusCorrected
|
|
||||||
slog.Info("TRDCORR: trade correction", "tradeReportID", tradeReportID, "refID", tradeReportRefID)
|
|
||||||
case "104": // TRDCXL — trade cancellation
|
|
||||||
status = domain.PostTradeStatusCancelled
|
|
||||||
slog.Info("TRDCXL: trade cancel", "tradeReportID", tradeReportID, "refID", tradeReportRefID)
|
|
||||||
case "105", "106", "107", "108": // log and ack only, no business logic
|
|
||||||
status = domain.PostTradeStatusActive
|
|
||||||
slog.Info("trade report (no business logic)", "tradeReportType", string(tradeReportType), "tradeReportID", tradeReportID)
|
|
||||||
default:
|
|
||||||
status = domain.PostTradeStatusActive
|
|
||||||
slog.Warn("unexpected TradeReportType", "tradeReportType", string(tradeReportType), "tradeReportID", tradeReportID)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.tradesMu.Lock()
|
m.tradesMu.Lock()
|
||||||
m.trades[tradeID] = &postTrade{
|
m.trades[tradeID] = trade
|
||||||
TradeID: tradeID,
|
|
||||||
TradeReportID: tradeReportID,
|
|
||||||
TradeReportType: string(tradeReportType),
|
|
||||||
Side: side,
|
|
||||||
LastQty: lastQty,
|
|
||||||
LastPx: lastPx,
|
|
||||||
SettlDate: settlDate,
|
|
||||||
TradeDate: tradeDate,
|
|
||||||
Status: status,
|
|
||||||
TWTradeID: twTradeID,
|
|
||||||
}
|
|
||||||
m.tradesMu.Unlock()
|
m.tradesMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +416,7 @@ func (m *Manager) loadTrades() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
trades := make(map[string]*postTrade)
|
trades := make(map[string]domain.TradeCaptureReport)
|
||||||
|
|
||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
switch msg.JMessage.MsgType {
|
switch msg.JMessage.MsgType {
|
||||||
@ -466,9 +431,9 @@ func (m *Manager) loadTrades() error {
|
|||||||
|
|
||||||
t, exists := trades[tradeID]
|
t, exists := trades[tradeID]
|
||||||
if !exists {
|
if !exists {
|
||||||
t = &postTrade{
|
t = domain.TradeCaptureReport{
|
||||||
TradeID: tradeID,
|
TradeID: tradeID,
|
||||||
Status: domain.PostTradeStatusActive,
|
// Status: domain.PostTradeStatusActive,
|
||||||
}
|
}
|
||||||
trades[tradeID] = t
|
trades[tradeID] = t
|
||||||
}
|
}
|
||||||
@ -503,60 +468,57 @@ func (m *Manager) loadTrades() error {
|
|||||||
t.TWTradeID = v
|
t.TWTradeID = v
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tradeReportType {
|
// switch tradeReportType {
|
||||||
case "103": // TRDCORR
|
// case "103": // TRDCORR
|
||||||
t.Status = domain.PostTradeStatusCorrected
|
// t.Status = domain.PostTradeStatusCorrected
|
||||||
case "104": // TRDCXL
|
// case "104": // TRDCXL
|
||||||
t.Status = domain.PostTradeStatusCancelled
|
// t.Status = domain.PostTradeStatusCancelled
|
||||||
default:
|
// default:
|
||||||
if t.Status != domain.PostTradeStatusCorrected && t.Status != domain.PostTradeStatusCancelled {
|
// if t.Status != domain.PostTradeStatusCorrected && t.Status != domain.PostTradeStatusCancelled {
|
||||||
t.Status = domain.PostTradeStatusActive
|
// t.Status = domain.PostTradeStatusActive
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
active := 0
|
// active := 0
|
||||||
for _, t := range trades {
|
// for _, t := range trades {
|
||||||
if t.Status == domain.PostTradeStatusActive {
|
// if t.Status == domain.PostTradeStatusActive {
|
||||||
active++
|
// active++
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
m.tradesMu.Lock()
|
m.tradesMu.Lock()
|
||||||
m.trades = trades
|
m.trades = trades
|
||||||
m.tradesMu.Unlock()
|
m.tradesMu.Unlock()
|
||||||
|
|
||||||
slog.Info("recovery completed", "totalTrades", len(trades), "activeTrades", active)
|
// slog.Info("recovery completed", "totalTrades", len(trades), "activeTrades", active)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTrades returns only active trades.
|
func (m *Manager) TradeCaptureReports() []domain.TradeCaptureReport {
|
||||||
func (m *Manager) GetTrades() []domain.PostTrade {
|
|
||||||
m.tradesMu.RLock()
|
m.tradesMu.RLock()
|
||||||
defer m.tradesMu.RUnlock()
|
defer m.tradesMu.RUnlock()
|
||||||
|
|
||||||
var result []domain.PostTrade
|
var result []domain.TradeCaptureReport
|
||||||
|
|
||||||
for _, t := range m.trades {
|
for _, t := range m.trades {
|
||||||
if t.Status == domain.PostTradeStatusActive {
|
result = append(result, t)
|
||||||
result = append(result, t.toPostTrade())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllTrades returns all trades regardless of status.
|
// GetAllTrades returns all trades regardless of status.
|
||||||
func (m *Manager) GetAllTrades() []domain.PostTrade {
|
func (m *Manager) GetAllTrades() []domain.TradeCaptureReport {
|
||||||
m.tradesMu.RLock()
|
m.tradesMu.RLock()
|
||||||
defer m.tradesMu.RUnlock()
|
defer m.tradesMu.RUnlock()
|
||||||
|
|
||||||
result := make([]domain.PostTrade, 0, len(m.trades))
|
result := make([]domain.TradeCaptureReport, 0, len(m.trades))
|
||||||
|
|
||||||
for _, t := range m.trades {
|
for _, t := range m.trades {
|
||||||
result = append(result, t.toPostTrade())
|
result = append(result, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -2,8 +2,8 @@ package domain
|
|||||||
|
|
||||||
import "github.com/shopspring/decimal"
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
// Trade represents data extracted from a TradeCaptureReport (35=AE).
|
// TradeCaptureReport represents data extracted from a TradeCaptureReport (35=AE).
|
||||||
type Trade struct {
|
type TradeCaptureReport struct {
|
||||||
TradeReportID string // 571
|
TradeReportID string // 571
|
||||||
TradeID string // 1003
|
TradeID string // 1003
|
||||||
ExecID string // 17
|
ExecID string // 17
|
||||||
|
|||||||
Reference in New Issue
Block a user