UDT-011: Localización Temporal Argentina (infra transversal) #25

Merged
dmolinari merged 24 commits from feature/UDT-011 into main 2026-04-18 13:57:49 +00:00
2 changed files with 50 additions and 2 deletions
Showing only changes of commit 3c264aa7a1 - Show all commits

View File

@@ -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<IAuthorizationHandler, PermissionAuthorizationHandler>();
builder.Services.AddSingleton<IAuthorizationMiddlewareResultHandler, ForbiddenProblemDetailsHandler>();
// 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<ExceptionFilter>();
}).AddJsonOptions(jsonOpts =>
{
jsonOpts.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
});
// OpenAPI / Scalar

View File

@@ -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 ────────────────────────────────
/// <summary>
/// [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.
/// </summary>
[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);
}
}
}