< Summary

Information
Line coverage
0%
Covered lines: 0
Uncovered lines: 242
Coverable lines: 242
Total lines: 328
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
<Main>$()0%110100%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Program.cs

#LineLine coverage
 1using System.Text;
 2using FAU.API.Middleware;
 3using FAU.API.Seeds;
 4using FAU.DataAccess;
 5using FAU.DataAccess.Repositories;
 6using FAU.Entidades.Auditoria;
 7using FAU.Logica.Calculators;
 8using FAU.Logica.Calculadores;
 9using FAU.Logica.Services;
 10using FAU.Logica.Services.InsumoValidators;
 11using Microsoft.AspNetCore.Authentication.JwtBearer;
 12using Microsoft.AspNetCore.Authorization;
 13using Microsoft.EntityFrameworkCore;
 14using Microsoft.IdentityModel.Tokens;
 15using Microsoft.OpenApi.Models;
 16using Microsoft.AspNetCore.HttpOverrides;
 17using QuestPDF.Infrastructure;
 18using Serilog;
 19
 20// Npgsql 7+ requiere Kind=UTC para timestamptz; habilitar comportamiento legacy para columnas timestamp sin zona
 021AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
 22
 023QuestPDF.Settings.License = LicenseType.Community;
 24
 025var builder = WebApplication.CreateBuilder(args);
 26
 27// Log del ambiente y configuración cargada
 028var environment = builder.Environment.EnvironmentName;
 029var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
 30
 031Console.WriteLine("=====================================");
 032Console.WriteLine($"Ambiente: {environment}");
 033Console.WriteLine("=====================================");
 34
 035builder.Services.AddDbContext<ApplicationDbContext>(options =>
 036    options.UseNpgsql(connectionString, o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)));
 37
 038Auditoria.IniciarAuditoria(builder.Configuration);
 39
 40// Redirigir ILogger<T> de todos los servicios/controladores hacia Serilog
 041builder.Logging.ClearProviders();
 042builder.Logging.AddSerilog(Log.Logger);
 43
 44// Configuración de JWT
 045var jwtKey = builder.Configuration["Jwt:Key"] ?? throw new InvalidOperationException("JWT Key no configurada");
 046var jwtIssuer = builder.Configuration["Jwt:Issuer"];
 047var jwtAudience = builder.Configuration["Jwt:Audience"];
 48
 049builder.Services.AddAuthentication(options =>
 050{
 051    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 052    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 053})
 054.AddJwtBearer(options =>
 055{
 056    options.RequireHttpsMetadata = false; // En producción debe ser true
 057    options.SaveToken = true;
 058    options.TokenValidationParameters = new TokenValidationParameters
 059    {
 060        ValidateIssuerSigningKey = true,
 061        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)),
 062        ValidateIssuer = true,
 063        ValidIssuer = jwtIssuer,
 064        ValidateAudience = true,
 065        ValidAudience = jwtAudience,
 066        ValidateLifetime = true,
 067        ClockSkew = TimeSpan.Zero
 068    };
 069});
 70
 071builder.Services.AddAuthorization();
 72
 73// HttpContext + Current user context (auditoría)
 074builder.Services.AddHttpContextAccessor();
 075builder.Services.AddScoped<FAU.Logica.Services.ICurrentUserContext, FAU.API.Services.CurrentUserContext>();
 76
 77// Registro de repositorios
 078builder.Services.AddScoped<IUsuarioRepository, UsuarioRepository>();
 079builder.Services.AddScoped<IRolRepository, RolRepository>();
 080builder.Services.AddScoped<IAuditoriaRepository, AuditoriaRepository>();
 081builder.Services.AddScoped<IBancoRepository, BancoRepository>();
 082builder.Services.AddScoped<IAcreedorRepository, AcreedorRepository>();
 083builder.Services.AddScoped<IPersonalRepository, PersonalRepository>();
 084builder.Services.AddScoped<IAguinaldosRepository, AguinaldosRepository>();
 085builder.Services.AddScoped<IAguinaldoBajaRepository, AguinaldoBajaRepository>();
 086builder.Services.AddScoped<IAguinaldoValidador, AguinaldoValidador>();
 087builder.Services.AddScoped<IAguinaldoSemestralService, AguinaldoSemestralService>();
 088builder.Services.AddScoped<IAguinaldoBajaService, AguinaldoBajaService>();
 089builder.Services.AddScoped<IAguinaldoHistoricoService, AguinaldoHistoricoService>();
 090builder.Services.AddScoped<IAguinaldoReciboService, AguinaldoReciboService>();
 091builder.Services.AddScoped<IAguinaldoPadronService, AguinaldoPadronService>();
 092builder.Services.AddScoped<IAguinaldoReporteControlService, AguinaldoReporteControlService>();
 093builder.Services.AddScoped<FAU.Logica.Services.AguinaldoCalculator>();
 094builder.Services.AddScoped<AguinaldoBajaCalculator>();
 095builder.Services.AddScoped<ITipoBeneficioRepository, TipoBeneficioRepository>();
 096builder.Services.AddScoped<IBeneficioSocialRepository, BeneficioSocialRepository>();
 097builder.Services.AddScoped<IBeneficioSocialBeneficiarioRepository, BeneficioSocialBeneficiarioRepository>();
 098builder.Services.AddScoped<IIrpfRepository, IrpfRepository>();
 099builder.Services.AddScoped<IDependienteRepository, DependienteRepository>();
 0100builder.Services.AddScoped<ICompensacionRepository, CompensacionRepository>();
 0101builder.Services.AddScoped<IParametroLiquidacionRepository, ParametroLiquidacionRepository>();
 0102builder.Services.AddScoped<IPeriodosRepository, PeriodosRepository>();
 0103builder.Services.AddScoped<INovedadPeriodoRepository, NovedadPeriodoRepository>();
 0104builder.Services.AddScoped<ISnapshotsRepository, SnapshotsRepository>();
 0105builder.Services.AddScoped<IUnidadRepository, UnidadRepository>();
 0106builder.Services.AddScoped<ITablaPermanenciaRepository, TablaPermanenciaRepository>();
 0107builder.Services.AddScoped<IEscalafonRepository, EscalafonRepository>();
 0108builder.Services.AddScoped<IGradoRepository, GradoRepository>();
 0109builder.Services.AddScoped<ISituacionRepository, SituacionRepository>();
 0110builder.Services.AddScoped<IProgramaRepository, ProgramaRepository>();
 0111builder.Services.AddScoped<ITipoMovimientoRepository, TipoMovimientoRepository>();
 0112builder.Services.AddScoped<IMotivoBajaRepository, MotivoBajaRepository>();
 0113builder.Services.AddScoped<IForm3100Repository, Form3100Repository>();
 0114builder.Services.AddScoped<IDescuentoPersonalRepository, DescuentoPersonalRepository>();
 0115builder.Services.AddScoped<IFictoPersonaRepository, FictoPersonaRepository>();
 0116builder.Services.AddScoped<ICompPersonal048018Repository, CompPersonal048018Repository>();
 0117builder.Services.AddScoped<IDocumentoRepository, DocumentoRepository>();
 0118builder.Services.AddScoped<IReciboRepository, ReciboRepository>();
 0119builder.Services.AddScoped<IArchivoOrganismoRepository, ArchivoOrganismoRepository>();
 0120builder.Services.AddScoped<IReportePresupuestalRepository, ReportePresupuestalRepository>();
 0121builder.Services.AddScoped<IReporteControlRepository, ReporteControlRepository>();
 0122builder.Services.AddScoped<IReporteDeficitRepository, ReporteDeficitRepository>();
 123
 124// Registro de servicios
 0125builder.Services.AddScoped<IAuthService, AuthService>();
 0126builder.Services.AddScoped<IUsuarioService, UsuarioService>();
 0127builder.Services.AddScoped<IRolService, RolService>();
 0128builder.Services.AddScoped<IAuditoriaCatalogoResolver, AuditoriaCatalogoResolver>();
 0129builder.Services.AddScoped<IAuditoriaService, AuditoriaService>();
 0130builder.Services.AddScoped<IBancoService, BancoService>();
 0131builder.Services.AddScoped<IAcreedorService, AcreedorService>();
 0132builder.Services.AddScoped<IPersonalService, PersonalService>();
 0133builder.Services.AddScoped<ITipoBeneficioService, TipoBeneficioService>();
 0134builder.Services.AddScoped<IBeneficioSocialService, BeneficioSocialService>();
 0135builder.Services.AddScoped<IBeneficioSocialBeneficiarioService, BeneficioSocialBeneficiarioService>();
 0136builder.Services.AddScoped<IDependienteService, DependienteService>();
 0137builder.Services.AddScoped<ICompensacionService, CompensacionService>();
 0138builder.Services.AddScoped<IParametroLiquidacionService, ParametroLiquidacionService>();
 0139builder.Services.AddScoped<IReciboService, ReciboService>();
 0140builder.Services.AddScoped<IArchivoOrganismoService, ArchivoOrganismoService>();
 0141builder.Services.AddScoped<IReportePresupuestalService, ReportePresupuestalService>();
 0142builder.Services.AddScoped<IReporteControlService, ReporteControlService>();
 0143builder.Services.AddScoped<IReporteDeficitService, ReporteDeficitService>();
 0144builder.Services.AddScoped<IInsumoValidator, LotesCompensacionValidator>();
 0145builder.Services.AddScoped<IInsumoValidator, BeneficiosSocialesValidator>();
 0146builder.Services.AddScoped<IInsumoValidator, NovedadesPeriodoValidator>();
 0147builder.Services.AddScoped<IInsumoValidator, DescuentosPersonalesPendientesValidator>();
 0148builder.Services.AddScoped<IInsumoValidator, RetroactividadesPendientesValidator>();
 0149builder.Services.AddScoped<IInsumoValidator, TablasReferenciaValidator>();
 0150builder.Services.AddScoped<IInsumoEvaluador, InsumoEvaluador>();
 0151builder.Services.AddScoped<IInsumosPeriodoLoader, InsumosPeriodoLoader>();
 0152builder.Services.AddScoped<IPeriodoService, PeriodoService>();
 0153builder.Services.AddScoped<INovedadPeriodoService, NovedadPeriodoService>();
 0154builder.Services.AddScoped<IPeriodoGuard, PeriodoGuard>();
 0155builder.Services.AddScoped<ILiquidacionService, LiquidacionService>();
 0156builder.Services.AddScoped<ICalcularDiferencia615Service, CalcularDiferencia615Service>();
 0157builder.Services.AddScoped<IProcesadorBeneficiosService, ProcesadorBeneficiosService>();
 0158builder.Services.AddScoped<IInstructivoBeneficiosService, InstructivoBeneficiosService>();
 0159builder.Services.AddScoped<Sit10Calculator>();
 0160builder.Services.AddScoped<Sit30Calculator>();
 0161builder.Services.AddScoped<Sit32Calculator>();
 0162builder.Services.AddScoped<Sit50Calculator>();
 0163builder.Services.AddScoped<Sit70Calculator>();
 0164builder.Services.AddScoped<SitCadeteCalculator>();
 0165builder.Services.AddScoped<FAU.Logica.Calculadores.AguinaldoCalculator>();
 0166builder.Services.AddScoped<ReservaCalculator>();
 0167builder.Services.AddScoped<ReservaSuperiorCalculator>();
 0168builder.Services.AddScoped<SitSubalternoReincorporadoCalculator>();
 0169builder.Services.AddScoped<ICalculadorFactory, CalculadorFactory>();
 0170builder.Services.AddScoped<IrpfCalculator>();
 0171builder.Services.AddScoped<IIrpfService, IrpfService>();
 0172builder.Services.AddScoped<IMotorAcumuladoresService, MotorAcumuladoresService>();
 0173builder.Services.AddScoped<IDeficitCalculator, DeficitCalculator>();
 0174builder.Services.AddScoped<IDescuentosLegalesCalculator, DescuentosLegalesCalculator>();
 0175builder.Services.AddScoped<IUnidadService, UnidadService>();
 0176builder.Services.AddScoped<ITablaPermanenciaService, TablaPermanenciaService>();
 0177builder.Services.AddScoped<IEscalafonService, EscalafonService>();
 0178builder.Services.AddScoped<IGradoService, GradoService>();
 0179builder.Services.AddScoped<ISituacionService, SituacionService>();
 0180builder.Services.AddScoped<IProgramaService, ProgramaService>();
 0181builder.Services.AddScoped<ITipoMovimientoService, TipoMovimientoService>();
 0182builder.Services.AddScoped<IMotivoBajaService, MotivoBajaService>();
 0183builder.Services.AddScoped<IForm3100Service, Form3100Service>();
 0184builder.Services.AddScoped<IDescuentoPersonalService, DescuentoPersonalService>();
 0185builder.Services.AddScoped<IFictoPersonaService, FictoPersonaService>();
 0186builder.Services.AddScoped<ICompPersonal048018Service, CompPersonal048018Service>();
 0187builder.Services.AddScoped<IStorageService, FilesystemStorageService>();
 188
 189// Add services to the container.
 0190builder.Services.AddControllers();
 191
 192// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 0193builder.Services.AddEndpointsApiExplorer();
 0194builder.Services.AddHealthChecks();
 0195builder.Services.AddSwaggerGen(c =>
 0196{
 0197    c.SwaggerDoc("v1", new OpenApiInfo
 0198    {
 0199        Title = "FAU Liquidación API",
 0200        Version = "v1",
 0201        Description = "API para el sistema de liquidación de la FAU"
 0202    });
 0203
 0204    // Configurar Swagger para usar JWT
 0205    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
 0206    {
 0207        Description = "JWT Authorization header usando el esquema Bearer. Ejemplo: \"Bearer {token}\"",
 0208        Name = "Authorization",
 0209        In = ParameterLocation.Header,
 0210        Type = SecuritySchemeType.ApiKey,
 0211        Scheme = "Bearer"
 0212    });
 0213
 0214    var xmlFile = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml";
 0215    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
 0216    c.IncludeXmlComments(xmlPath);
 0217
 0218    c.AddSecurityRequirement(new OpenApiSecurityRequirement
 0219    {
 0220        {
 0221            new OpenApiSecurityScheme
 0222            {
 0223                Reference = new OpenApiReference
 0224                {
 0225                    Type = ReferenceType.SecurityScheme,
 0226                    Id = "Bearer"
 0227                }
 0228            },
 0229            Array.Empty<string>()
 0230        }
 0231    });
 0232});
 233
 234// Configuración de CORS (opcional, para desarrollo)
 0235builder.Services.AddCors(options =>
 0236{
 0237    options.AddPolicy("AllowAll", policy =>
 0238    {
 0239        policy.AllowAnyOrigin()
 0240              .AllowAnyMethod()
 0241              .AllowAnyHeader();
 0242    });
 0243});
 244
 0245var app = builder.Build();
 246
 247// Forwarded headers (si está detrás de proxy / ingress)
 0248app.UseForwardedHeaders(new ForwardedHeadersOptions
 0249{
 0250    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
 0251});
 252
 253// Comando de seeding: dotnet run --seed-admin
 254// Crea el primer usuario Administrador y termina sin levantar el servidor HTTP.
 0255if (args.Contains("--seed-admin"))
 256{
 0257    using var scope = app.Services.CreateScope();
 0258    var exitCode = await SuperAdminSeeder.RunAsync(args, scope.ServiceProvider);
 0259    Environment.Exit(exitCode);
 0260    return;
 261}
 262
 263// Validar conexión a la base de datos al inicio
 0264using (var scope = app.Services.CreateScope())
 265{
 0266    var services = scope.ServiceProvider;
 267    try
 268    {
 0269        var context = services.GetRequiredService<ApplicationDbContext>();
 0270        var canConnect = context.Database.CanConnect();
 271
 0272        if (!canConnect)
 273        {
 0274            app.Logger.LogError("No se pudo conectar a la base de datos");
 0275            throw new Exception("No se pudo establecer conexión con la base de datos");
 276        }
 0277    }
 0278    catch (Exception ex)
 279    {
 0280        app.Logger.LogError(ex, "Error al validar la conexión a la base de datos: {Message}", ex.Message);
 0281        throw;
 282    }
 0283}
 284
 285// Validar configuración de Storage:BasePath (no crítica en desarrollo)
 286{
 0287    var storageBasePath = app.Configuration["Storage:BasePath"];
 0288    if (string.IsNullOrWhiteSpace(storageBasePath))
 289    {
 0290        app.Logger.LogWarning("Storage:BasePath no está configurado. La carga/descarga de archivos (Form 3100) no estará
 291    }
 0292    else if (!Directory.Exists(storageBasePath))
 293    {
 0294        app.Logger.LogWarning(
 0295            "Storage:BasePath configurado pero el directorio no existe: {Path}. " +
 0296            "Se creará al subir el primer archivo.",
 0297            storageBasePath);
 298    }
 299    else
 300    {
 0301        app.Logger.LogInformation("Storage:BasePath OK: {Path}", storageBasePath);
 302    }
 303}
 304
 305// Configure the HTTP request pipeline.
 306// Habilitar Swagger en todos los ambientes (útil para Docker)
 0307app.UseSwagger();
 0308app.UseSwaggerUI(c =>
 0309{
 0310    c.SwaggerEndpoint("/swagger/v1/swagger.json", "FAU Liquidación API v1");
 0311});
 312
 0313app.UseHttpsRedirection();
 314
 0315app.UseCors("AllowAll");
 316
 0317app.UseAuthentication(); // IMPORTANTE: debe ir antes de UseAuthorization
 0318app.UseMiddleware<LogUserEnricherMiddleware>(); // Enriquece logs con el usuario autenticado
 0319app.UseAuthorization();
 320
 321
 0322app.MapHealthChecks("/health");
 0323app.MapControllers();
 324
 0325app.Run();
 326
 327// Expone la clase Program para WebApplicationFactory en tests de integración
 328public partial class Program { }

Methods/Properties

<Main>$()