refactor: save current workspace state including FinlyticAnalyzer fixes, FinlyticApp trade route alignment, and DTO audit documentation

This commit is contained in:
2026-08-12 18:30:42 +02:00
parent a9553e9fbf
commit 3d8af3940b
163 changed files with 3421 additions and 1751 deletions
@@ -271,16 +271,14 @@ public class AssetsController : ControllerBase
/// <summary>
/// Serviert das SVG-Logo direkt aus dem gemounteten Docker Volume (Volumes.LogosRelativePath).
/// </summary>
[HttpGet("logo/{isin}")]
[HttpGet("/api/v1/logo/{isin}")]
[AllowAnonymous]
public async Task<IActionResult> GetAssetLogo([FromRoute] string isin)
{
if (string.IsNullOrWhiteSpace(isin)) return NotFound();
string cleanIsin = isin.Trim().ToUpperInvariant();
// Path Traversal Guard
string safeFileName = string.Concat(cleanIsin.Where(c => char.IsLetterOrDigit(c) || c == '_' || c == '-')) + ".svg";
string logoPath = Path.Combine(Volumes.LogosRelativePath, safeFileName);
string logoPath = Path.Combine(Volumes.LogosRelativePath, $"{isin}.svg");
if (System.IO.File.Exists(logoPath))
{
@@ -13,27 +13,6 @@ using Microsoft.Extensions.Logging;
namespace FinlyticBackend.Controllers;
/// <summary>
/// Response DTO for corporate calendar events (AOT-compliant).
/// </summary>
public record CalendarEventResponseDto(
[property: JsonPropertyName("id")] string Id,
[property: JsonPropertyName("symbol")] string Symbol,
[property: JsonPropertyName("companyName")]
string CompanyName,
[property: JsonPropertyName("eventType")]
string EventType,
[property: JsonPropertyName("eventDate")]
DateTime EventDate,
[property: JsonPropertyName("date")] string Date,
[property: JsonPropertyName("isin")] string Isin,
[property: JsonPropertyName("ticker")] string Ticker,
[property: JsonPropertyName("description")]
string Description,
[property: JsonPropertyName("details")]
string Details,
[property: JsonPropertyName("image")] string Image
);
[ApiController]
[Authorize]
@@ -52,22 +31,26 @@ public class CalendarController : ControllerBase
/// <summary>
/// Retrieves corporate calendar events with optional filters.
/// </summary>
[HttpGet("events")]
[HttpGet("events/{year:int?}/{month:int?}")]
public async Task<IActionResult> GetCorporateCalendar(
int? year = null,
int? month = null,
[FromQuery] string? category = null,
[FromQuery] DateTime? date = null,
[FromQuery] string? symbol = null,
[FromQuery] string? isin = null)
{
string? activeSymbol = !string.IsNullOrWhiteSpace(symbol) ? symbol.Trim() : isin?.Trim();
int targetYear = year ?? DateTime.UtcNow.Year;
int targetMonth = month ?? DateTime.UtcNow.Month;
try
{
if (_mqttClient.IsConnected)
{
var rawEvents = await _mqttClient.SendRpcRequestAsync<List<CorporateEventDto>, EmptyRequest>(
"events_GetAll",
new EmptyRequest(),
var rawEvents = await _mqttClient.SendRpcRequestAsync<List<CorporateEventDto>, GetEventsByMonthRequest>(
"events_GetByMonth",
new GetEventsByMonthRequest(targetYear, targetMonth),
TimeSpan.FromSeconds(4)
);
@@ -50,12 +50,6 @@ public class NewsController : ControllerBase
effectiveStatus = "Analyzed";
}
string? dateStr = !string.IsNullOrWhiteSpace(date) ? date.Trim() : null;
if (string.Equals(dateStr, "today", StringComparison.OrdinalIgnoreCase))
{
dateStr = DateTime.UtcNow.ToString("yyyy-MM-dd");
}
try
{
if (_mqttClient.IsConnected)
@@ -64,11 +58,13 @@ public class NewsController : ControllerBase
Limit: pageSize,
Offset: (page - 1) * pageSize,
Isin: activeSymbol,
Date: dateStr,
Date: DateTime.TryParse(date, out var dateTime) ? dateTime : null,
Status: effectiveStatus,
Query: query,
HasSentiment: hasSentiment
);
_logger.LogInformation("[payload] " + payload.Date.ToString());
var articles = await _mqttClient.SendRpcRequestAsync<List<NewsArticleDto>, DailyNewsRequest>(
"news_Get",