From 3c264aa7a1db9b3f41ae37b5c1eed993990e7fe7 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Sat, 18 Apr 2026 09:47:19 -0300 Subject: [PATCH] chore(udt-011): register DateOnlyJsonConverter in Program.cs AddJsonOptions --- src/api/SIGCM2.Api/Program.cs | 10 ++++- .../Admin/FiscalControllerTests.cs | 42 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/api/SIGCM2.Api/Program.cs b/src/api/SIGCM2.Api/Program.cs index 92ab9f8..1000af3 100644 --- a/src/api/SIGCM2.Api/Program.cs +++ b/src/api/SIGCM2.Api/Program.cs @@ -2,12 +2,13 @@ using Microsoft.AspNetCore.Authorization; using Serilog; using Scalar.AspNetCore; using SIGCM2.Api.Authorization; +using SIGCM2.Api.Filters; using SIGCM2.Api.HealthChecks; +using SIGCM2.Api.Json; using SIGCM2.Api.Middleware; using SIGCM2.Application; using SIGCM2.Infrastructure; using SIGCM2.Infrastructure.Audit.Jobs; -using SIGCM2.Api.Filters; // Bootstrap logger — before DI is built Log.Logger = new LoggerConfiguration() @@ -36,10 +37,15 @@ builder.Services.AddAuthorization(); builder.Services.AddScoped(); builder.Services.AddSingleton(); -// Controllers with exception filter +// Controllers with exception filter + JSON options +// UDT-011: DateOnlyJsonConverter ensures Cat2 date fields serialize as "yyyy-MM-dd" +// and never as "2026-05-01T00:00:00" or with a UTC "Z" suffix. builder.Services.AddControllers(opts => { opts.Filters.Add(); +}).AddJsonOptions(jsonOpts => +{ + jsonOpts.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter()); }); // OpenAPI / Scalar diff --git a/tests/SIGCM2.Api.Tests/Admin/FiscalControllerTests.cs b/tests/SIGCM2.Api.Tests/Admin/FiscalControllerTests.cs index 704b380..9c7ed2b 100644 --- a/tests/SIGCM2.Api.Tests/Admin/FiscalControllerTests.cs +++ b/tests/SIGCM2.Api.Tests/Admin/FiscalControllerTests.cs @@ -693,4 +693,46 @@ public sealed class FiscalControllerTests : IAsyncLifetime Assert.True(json.TryGetProperty("items", out _), "Response must have 'items'"); Assert.True(json.TryGetProperty("total", out _), "Response must have 'total'"); } + + // ── UDT-011: DateOnly serialization format ──────────────────────────────── + + /// + /// [UDT-011 REQ-BE-JSON-001] POST /iva → vigenciaDesde en respuesta debe ser + /// "yyyy-MM-dd" (e.g. "2025-01-01"), no "2025-01-01T00:00:00" ni con sufijo "Z". + /// Valida que DateOnlyJsonConverter está activo en el pipeline de controllers. + /// + [Fact] + public async Task CreateIva_VigenciaDesde_SerializesAsDateOnlyString() + { + const string codigo = "IVA_9999"; + var token = await GetAdminTokenAsync(); + try + { + using var req = BuildRequest(HttpMethod.Post, IvaEndpoint, new + { + codigo, + descripcion = "IVA DateOnly Format Test", + porcentaje = 5.0m, + aplicaIVA = true, + vigenciaDesde = "2025-01-01" + }, token); + var resp = await _client.SendAsync(req); + + Assert.Equal(HttpStatusCode.Created, resp.StatusCode); + + // Read raw JSON string to inspect format (not deserialized) + var rawJson = await resp.Content.ReadAsStringAsync(); + + // vigenciaDesde MUST be "2025-01-01" — short date format + Assert.Contains("\"2025-01-01\"", rawJson); + + // Must NOT contain datetime format or UTC suffix + Assert.DoesNotContain("T00:00:00", rawJson); + Assert.DoesNotContain("\"2025-01-01Z\"", rawJson); + } + finally + { + await DeleteTipoDeIvaByCodigoAsync(codigo); + } + } }