Add strategies paginated

This commit is contained in:
2025-10-07 01:21:25 +07:00
parent 85000644a6
commit f43117e6c6
2 changed files with 154 additions and 49 deletions

View File

@@ -1,5 +1,6 @@
using Managing.Api.Models.Requests;
using Managing.Api.Models.Responses;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Grains;
using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot.Commands;
@@ -38,6 +39,7 @@ public class DataController : ControllerBase
private readonly ITradingService _tradingService;
private readonly IGrainFactory _grainFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IBotService _botService;
/// <summary>
/// Initializes a new instance of the <see cref="DataController"/> class.
@@ -52,6 +54,7 @@ public class DataController : ControllerBase
/// <param name="tradingService">Service for trading operations.</param>
/// <param name="grainFactory">Orleans grain factory for accessing grains.</param>
/// <param name="serviceScopeFactory">Service scope factory for creating scoped services.</param>
/// <param name="botService">Service for bot operations.</param>
public DataController(
IExchangeService exchangeService,
IAccountService accountService,
@@ -61,7 +64,8 @@ public class DataController : ControllerBase
IMediator mediator,
ITradingService tradingService,
IGrainFactory grainFactory,
IServiceScopeFactory serviceScopeFactory)
IServiceScopeFactory serviceScopeFactory,
IBotService botService)
{
_exchangeService = exchangeService;
_accountService = accountService;
@@ -72,6 +76,7 @@ public class DataController : ControllerBase
_tradingService = tradingService;
_grainFactory = grainFactory;
_serviceScopeFactory = serviceScopeFactory;
_botService = botService;
}
/// <summary>
@@ -765,6 +770,86 @@ public class DataController : ControllerBase
};
}
/// <summary>
/// Retrieves a paginated list of strategies (bots) excluding those with Saved status
/// </summary>
/// <param name="pageNumber">Page number (1-based, defaults to 1)</param>
/// <param name="pageSize">Number of items per page (defaults to 10, max 100)</param>
/// <param name="name">Filter by name (partial match, case-insensitive)</param>
/// <param name="ticker">Filter by ticker (partial match, case-insensitive)</param>
/// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param>
/// <param name="sortBy">Sort field (defaults to CreateDate)</param>
/// <param name="sortDirection">Sort direction - "Asc" or "Desc" (defaults to "Desc")</param>
/// <returns>A paginated list of strategies excluding Saved status bots</returns>
[HttpGet("GetStrategiesPaginated")]
public async Task<ActionResult<PaginatedResponse<TradingBotResponse>>> GetStrategiesPaginated(
int pageNumber = 1,
int pageSize = 10,
string? name = null,
string? ticker = null,
string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc")
{
// Validate pagination parameters
if (pageNumber < 1)
{
return BadRequest("Page number must be greater than 0");
}
if (pageSize < 1 || pageSize > 100)
{
return BadRequest("Page size must be between 1 and 100");
}
// Validate sort direction
if (sortDirection != "Asc" && sortDirection != "Desc")
{
return BadRequest("Sort direction must be 'Asc' or 'Desc'");
}
try
{
// Get paginated bots excluding Saved status
var (bots, totalCount) = await _botService.GetBotsPaginatedAsync(
pageNumber,
pageSize,
null, // No specific status filter - we'll exclude Saved in the service call
name,
ticker,
agentName,
sortBy,
sortDirection);
// Filter out Saved status bots
var filteredBots = bots.Where(bot => bot.Status != BotStatus.Saved).ToList();
var filteredCount = totalCount - bots.Count(bot => bot.Status == BotStatus.Saved);
// Map to response objects
var tradingBotResponses = MapBotsToTradingBotResponse(filteredBots);
// Calculate pagination metadata
var totalPages = (int)Math.Ceiling((double)filteredCount / pageSize);
var response = new PaginatedResponse<TradingBotResponse>
{
Items = tradingBotResponses.ToList(),
TotalCount = filteredCount,
PageNumber = pageNumber,
PageSize = pageSize,
TotalPages = totalPages,
HasPreviousPage = pageNumber > 1,
HasNextPage = pageNumber < totalPages
};
return Ok(response);
}
catch (Exception ex)
{
return StatusCode(500, $"Error retrieving strategies: {ex.Message}");
}
}
/// <summary>
/// Maps a Position domain object to a PositionViewModel
/// </summary>
@@ -789,4 +874,35 @@ public class DataController : ControllerBase
Identifier = position.Identifier,
};
}
/// <summary>
/// Maps a collection of Bot entities to TradingBotResponse objects.
/// </summary>
/// <param name="bots">The collection of bots to map</param>
/// <returns>A list of TradingBotResponse objects</returns>
private static List<TradingBotResponse> MapBotsToTradingBotResponse(IEnumerable<Bot> bots)
{
var list = new List<TradingBotResponse>();
foreach (var item in bots)
{
list.Add(new TradingBotResponse
{
Status = item.Status.ToString(),
WinRate = (item.TradeWins + item.TradeLosses) != 0
? item.TradeWins / (item.TradeWins + item.TradeLosses)
: 0,
ProfitAndLoss = item.Pnl,
Roi = item.Roi,
Identifier = item.Identifier.ToString(),
AgentName = item.User.AgentName,
CreateDate = item.CreateDate,
StartupTime = item.StartupTime,
Name = item.Name,
Ticker = item.Ticker,
});
}
return list;
}
}