Fix Reports 400 errors: normalize DateTime to UTC and restore camelCase JSON
Query-bound DateTimes have Kind=Unspecified which Npgsql rejects for timestamptz columns, causing InvalidOperationException caught as 400. Also add explicit CamelCase naming policy lost when AddJsonOptions was introduced for the enum converter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,17 +18,20 @@ public class ReportsController : ControllerBase
|
|||||||
|
|
||||||
[HttpGet("spending-by-category")]
|
[HttpGet("spending-by-category")]
|
||||||
public async Task<ActionResult<SpendingByCategoryReport>> SpendingByCategory([FromQuery] DateTime startDate, [FromQuery] DateTime endDate, [FromQuery] Guid? accountId)
|
public async Task<ActionResult<SpendingByCategoryReport>> SpendingByCategory([FromQuery] DateTime startDate, [FromQuery] DateTime endDate, [FromQuery] Guid? accountId)
|
||||||
=> Ok(await _reportService.GetSpendingByCategoryAsync(UserId, startDate, endDate, accountId));
|
=> Ok(await _reportService.GetSpendingByCategoryAsync(UserId, Utc(startDate), Utc(endDate), accountId));
|
||||||
|
|
||||||
[HttpGet("income-vs-expense")]
|
[HttpGet("income-vs-expense")]
|
||||||
public async Task<ActionResult<IncomeVsExpenseReport>> IncomeVsExpense([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
public async Task<ActionResult<IncomeVsExpenseReport>> IncomeVsExpense([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
||||||
=> Ok(await _reportService.GetIncomeVsExpenseAsync(UserId, startDate, endDate));
|
=> Ok(await _reportService.GetIncomeVsExpenseAsync(UserId, Utc(startDate), Utc(endDate)));
|
||||||
|
|
||||||
[HttpGet("net-worth")]
|
[HttpGet("net-worth")]
|
||||||
public async Task<ActionResult<NetWorthReport>> NetWorth([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
public async Task<ActionResult<NetWorthReport>> NetWorth([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
||||||
=> Ok(await _reportService.GetNetWorthAsync(UserId, startDate, endDate));
|
=> Ok(await _reportService.GetNetWorthAsync(UserId, Utc(startDate), Utc(endDate)));
|
||||||
|
|
||||||
[HttpGet("cash-flow")]
|
[HttpGet("cash-flow")]
|
||||||
public async Task<ActionResult<CashFlowReport>> CashFlow([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
public async Task<ActionResult<CashFlowReport>> CashFlow([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
||||||
=> Ok(await _reportService.GetCashFlowAsync(UserId, startDate, endDate));
|
=> Ok(await _reportService.GetCashFlowAsync(UserId, Utc(startDate), Utc(endDate)));
|
||||||
|
|
||||||
|
private static DateTime Utc(DateTime dt) =>
|
||||||
|
dt.Kind == DateTimeKind.Unspecified ? DateTime.SpecifyKind(dt, DateTimeKind.Utc) : dt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ builder.Services.AddSignalR();
|
|||||||
builder.Services.AddControllers()
|
builder.Services.AddControllers()
|
||||||
.AddJsonOptions(options =>
|
.AddJsonOptions(options =>
|
||||||
{
|
{
|
||||||
|
options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
|
||||||
options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
||||||
});
|
});
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
|||||||
Reference in New Issue
Block a user