Refactor pagination sorting parameters across multiple controllers and services to use the new SortDirection enum; update related API models and TypeScript definitions for consistency. Fix minor documentation and naming inconsistencies in the Bot and Data controllers.

This commit is contained in:
2025-12-14 20:23:26 +07:00
parent cb6b52ef4a
commit bcb00b9a86
30 changed files with 251 additions and 202 deletions

View File

@@ -206,7 +206,7 @@ public class PostgreSqlBotRepository : IBotRepository
string? ticker = null,
string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc",
SortDirection sortDirection = SortDirection.Desc,
bool showOnlyProfitable = false)
{
// Build the query with filters
@@ -249,33 +249,33 @@ public class PostgreSqlBotRepository : IBotRepository
// Apply sorting
query = sortBy switch
{
BotSortableColumn.Name => sortDirection.ToLower() == "asc"
BotSortableColumn.Name => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.Name)
: query.OrderByDescending(b => b.Name),
BotSortableColumn.Ticker => sortDirection.ToLower() == "asc"
BotSortableColumn.Ticker => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.Ticker)
: query.OrderByDescending(b => b.Ticker),
BotSortableColumn.Status => sortDirection.ToLower() == "asc"
BotSortableColumn.Status => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.Status)
: query.OrderByDescending(b => b.Status),
BotSortableColumn.StartupTime => sortDirection.ToLower() == "asc"
BotSortableColumn.StartupTime => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.StartupTime)
: query.OrderByDescending(b => b.StartupTime),
BotSortableColumn.Roi => sortDirection.ToLower() == "asc"
BotSortableColumn.Roi => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.Roi)
: query.OrderByDescending(b => b.Roi),
BotSortableColumn.Pnl => sortDirection.ToLower() == "asc"
BotSortableColumn.Pnl => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.Pnl)
: query.OrderByDescending(b => b.Pnl),
BotSortableColumn.WinRate => sortDirection.ToLower() == "asc"
BotSortableColumn.WinRate => sortDirection == SortDirection.Asc
? query.OrderBy(b =>
(b.TradeWins + b.TradeLosses) > 0 ? (double)b.TradeWins / (b.TradeWins + b.TradeLosses) : 0)
: query.OrderByDescending(b =>
(b.TradeWins + b.TradeLosses) > 0 ? (double)b.TradeWins / (b.TradeWins + b.TradeLosses) : 0),
BotSortableColumn.AgentName => sortDirection.ToLower() == "asc"
BotSortableColumn.AgentName => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.User.AgentName)
: query.OrderByDescending(b => b.User.AgentName),
_ => sortDirection.ToLower() == "asc"
_ => sortDirection == SortDirection.Asc
? query.OrderBy(b => b.CreateDate)
: query.OrderByDescending(b => b.CreateDate)
};

View File

@@ -360,7 +360,9 @@ public static class PostgreSqlMappers
Duration = backtest.EndDate - backtest.StartDate,
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement, jsonSettings),
UserId = backtest.User?.Id ?? 0,
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics, jsonSettings) : null,
StatisticsJson = backtest.Statistics != null
? JsonConvert.SerializeObject(backtest.Statistics, jsonSettings)
: null,
SharpeRatio = backtest.Statistics?.SharpeRatio ?? 0m,
MaxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0m,
MaxDrawdownRecoveryTime = backtest.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
@@ -503,7 +505,7 @@ public static class PostgreSqlMappers
return new ScenarioEntity
{
Name = scenario.Name,
LoopbackPeriod = scenario.LoopbackPeriod ?? 1,
LoopbackPeriod = scenario.LookbackPeriod,
UserId = scenario.User?.Id ?? 0
};
}

View File

@@ -13,7 +13,8 @@ namespace Managing.Infrastructure.Databases.PostgreSql;
public class PostgreSqlTradingRepository : BaseRepositoryWithLogging, ITradingRepository
{
public PostgreSqlTradingRepository(ManagingDbContext context, ILogger<SqlQueryLogger> logger, SentrySqlMonitoringService sentryMonitoringService)
public PostgreSqlTradingRepository(ManagingDbContext context, ILogger<SqlQueryLogger> logger,
SentrySqlMonitoringService sentryMonitoringService)
: base(context, logger, sentryMonitoringService)
{
}
@@ -154,7 +155,7 @@ public class PostgreSqlTradingRepository : BaseRepositoryWithLogging, ITradingRe
if (entity != null)
{
entity.LoopbackPeriod = scenario.LoopbackPeriod ?? 1;
entity.LoopbackPeriod = scenario.LookbackPeriod;
entity.UserId = scenario.User?.Id ?? 0;
entity.UpdatedAt = DateTime.UtcNow;
@@ -408,62 +409,63 @@ public class PostgreSqlTradingRepository : BaseRepositoryWithLogging, ITradingRe
public async Task UpdatePositionAsync(Position position)
{
await ExecuteWithLoggingAsync(async () =>
{
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var entity = _context.Positions
.AsTracking()
.Include(p => p.OpenTrade)
.Include(p => p.StopLossTrade)
.Include(p => p.TakeProfit1Trade)
.Include(p => p.TakeProfit2Trade)
.FirstOrDefault(p => p.Identifier == position.Identifier);
if (entity != null)
try
{
entity.ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0;
entity.NetPnL = position.ProfitAndLoss?.Net ?? 0;
entity.UiFees = position.UiFees;
// entity.OriginDirection = position.OriginDirection;
entity.GasFees = position.GasFees;
entity.Status = position.Status;
entity.MoneyManagementJson = position.MoneyManagement != null
? JsonConvert.SerializeObject(position.MoneyManagement)
: null;
entity.UpdatedAt = DateTime.UtcNow;
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
// Update related trades directly through the position's trade references
// This ensures we're updating the correct trade records for this specific position
if (position.Open != null && entity.OpenTrade != null)
var entity = _context.Positions
.AsTracking()
.Include(p => p.OpenTrade)
.Include(p => p.StopLossTrade)
.Include(p => p.TakeProfit1Trade)
.Include(p => p.TakeProfit2Trade)
.FirstOrDefault(p => p.Identifier == position.Identifier);
if (entity != null)
{
UpdateTradeEntity(entity.OpenTrade, position.Open);
}
entity.ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0;
entity.NetPnL = position.ProfitAndLoss?.Net ?? 0;
entity.UiFees = position.UiFees;
// entity.OriginDirection = position.OriginDirection;
entity.GasFees = position.GasFees;
entity.Status = position.Status;
entity.MoneyManagementJson = position.MoneyManagement != null
? JsonConvert.SerializeObject(position.MoneyManagement)
: null;
entity.UpdatedAt = DateTime.UtcNow;
if (position.StopLoss != null && entity.StopLossTrade != null)
{
UpdateTradeEntity(entity.StopLossTrade, position.StopLoss);
}
// Update related trades directly through the position's trade references
// This ensures we're updating the correct trade records for this specific position
if (position.Open != null && entity.OpenTrade != null)
{
UpdateTradeEntity(entity.OpenTrade, position.Open);
}
if (position.TakeProfit1 != null && entity.TakeProfit1Trade != null)
{
UpdateTradeEntity(entity.TakeProfit1Trade, position.TakeProfit1);
}
if (position.StopLoss != null && entity.StopLossTrade != null)
{
UpdateTradeEntity(entity.StopLossTrade, position.StopLoss);
}
if (position.TakeProfit2 != null && entity.TakeProfit2Trade != null)
{
UpdateTradeEntity(entity.TakeProfit2Trade, position.TakeProfit2);
}
if (position.TakeProfit1 != null && entity.TakeProfit1Trade != null)
{
UpdateTradeEntity(entity.TakeProfit1Trade, position.TakeProfit1);
}
await _context.SaveChangesAsync();
if (position.TakeProfit2 != null && entity.TakeProfit2Trade != null)
{
UpdateTradeEntity(entity.TakeProfit2Trade, position.TakeProfit2);
}
await _context.SaveChangesAsync();
}
}
}
finally
{
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}, nameof(UpdatePositionAsync), ("positionIdentifier", position.Identifier), ("positionStatus", position.Status));
finally
{
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}, nameof(UpdatePositionAsync), ("positionIdentifier", position.Identifier),
("positionStatus", position.Status));
}
/// <summary>
@@ -474,7 +476,7 @@ public class PostgreSqlTradingRepository : BaseRepositoryWithLogging, ITradingRe
{
// Only update the date if the trade status is changing from Requested to Filled
// This prevents overwriting dates for trades that are already filled
if (entity.Status != trade.Status)
if (entity.Status != trade.Status)
{
entity.Date = trade.Date;
}