< Summary

Information
Class: FAU.Logica.Services.NovedadPeriodoService
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/NovedadPeriodoService.cs
Line coverage
45%
Covered lines: 94
Uncovered lines: 112
Coverable lines: 206
Total lines: 354
Line coverage: 45.6%
Branch coverage
25%
Covered branches: 24
Total branches: 96
Branch coverage: 25%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
GetByIdAsync()100%210%
GetAllAsync()100%210%
GetPaginatedAsync()0%4260%
CreateAsync()56.25%383281.66%
UpdateAsync()0%1482380%
ChangeStateToConfirmedAsync()50%6689.47%
ChangeStateToAppliedAsync()50%19629.41%
DeleteAsync()0%4260%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/NovedadPeriodoService.cs

#LineLine coverage
 1using FAU.DataAccess.Repositories;
 2using FAU.Entidades;
 3using FAU.Logica.DTOs;
 4using Microsoft.Extensions.Logging;
 5
 6namespace FAU.Logica.Services;
 7
 8public class NovedadPeriodoService : INovedadPeriodoService
 9{
 110    private static readonly IReadOnlySet<string> TiposPermitidos = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
 111    {
 112        "ENFERMEDAD",
 113        "LICENCIA",
 114        "AUSENCIA_INJUSTIFICADA",
 115        "LICENCIA_SIN_PAGO",
 116        "MATERNIDAD",
 117        "CALAMIDAD_DOMESTICA"
 118    };
 19
 20    private readonly INovedadPeriodoRepository _novedadPeriodoRepository;
 21    private readonly IPeriodosRepository _periodosRepository;
 22    private readonly IPersonalRepository _personalRepository;
 23    private readonly IAuditoriaService _auditoriaService;
 24    private readonly ICurrentUserContext _currentUser;
 25    private readonly ILogger<NovedadPeriodoService> _logger;
 26
 427    public NovedadPeriodoService(
 428        INovedadPeriodoRepository novedadPeriodoRepository,
 429        IPeriodosRepository periodosRepository,
 430        IPersonalRepository personalRepository,
 431        IAuditoriaService auditoriaService,
 432        ICurrentUserContext currentUser,
 433        ILogger<NovedadPeriodoService> logger)
 34    {
 435        _novedadPeriodoRepository = novedadPeriodoRepository;
 436        _periodosRepository = periodosRepository;
 437        _personalRepository = personalRepository;
 438        _auditoriaService = auditoriaService;
 439        _currentUser = currentUser;
 440        _logger = logger;
 441    }
 42
 43    public async Task<NovedadPeriodo?> GetByIdAsync(long id)
 44    {
 045        return await _novedadPeriodoRepository.GetByIdAsync(id);
 046    }
 47
 48    public async Task<IEnumerable<NovedadPeriodo>> GetAllAsync()
 49    {
 050        return await _novedadPeriodoRepository.GetAllAsync();
 051    }
 52
 53    public async Task<PagedResult<NovedadPeriodoDto>> GetPaginatedAsync(
 54        int page,
 55        int pageSize,
 56        long? periodoId = null,
 57        long? personaId = null,
 58        string? tipo = null,
 59        string? estado = null)
 60    {
 061        if (page < 1) page = 1;
 062        if (pageSize < 1) pageSize = 10;
 063        if (pageSize > 100) pageSize = 100;
 64
 065        var (items, totalCount) = await _novedadPeriodoRepository.GetPaginatedAsync(page, pageSize, periodoId, personaId
 66
 067        var dtos = items.Select(n => new NovedadPeriodoDto
 068        {
 069            Id = n.Id,
 070            PeriodoId = n.PeriodoId,
 071            PersonaId = n.PersonaId,
 072            Tipo = n.Tipo,
 073            DiasAfectados = n.DiasAfectados,
 074            PorcentajeSubsidio = n.PorcentajeSubsidio,
 075            FechaDesde = n.FechaDesde ?? DateTime.MinValue,
 076            Observaciones = n.Observaciones,
 077            Estado = n.Estado,
 078            CreadoPor = n.CreadoPor,
 079            CreadoEn = n.CreadoEn,
 080            ConfirmadoPor = n.ConfirmadoPor,
 081            ConfirmadoEn = n.ConfirmadoEn
 082        })
 083        .ToList();
 84
 085        return new PagedResult<NovedadPeriodoDto>
 086        {
 087            Items = dtos,
 088            Page = page,
 089            PageSize = pageSize,
 090            TotalCount = totalCount
 091        };
 092    }
 93
 94    public async Task<(bool Success, NovedadPeriodo? Result, string? Error)> CreateAsync(CrearNovedadPeriodoRequest requ
 95    {
 296        if (request == null)
 97        {
 098            return (false, null, "La solicitud de creación es obligatoria");
 99        }
 100
 2101        if (request.PeriodoId <= 0)
 102        {
 0103            return (false, null, "El PeriodoId es requerido");
 104        }
 105
 2106        if (request.PersonaId <= 0)
 107        {
 0108            return (false, null, "El PersonaId es requerido");
 109        }
 110
 2111        if (string.IsNullOrWhiteSpace(request.Tipo))
 112        {
 0113            return (false, null, "El tipo de novedad es requerido");
 114        }
 115
 2116        if (!TiposPermitidos.Contains(request.Tipo.Trim()))
 117        {
 0118            return (false, null, "El tipo de novedad no es válido");
 119        }
 120
 2121        if (request.DiasAfectados < 1 || request.DiasAfectados > 30)
 122        {
 0123            return (false, null, "Los días afectados deben estar entre 1 y 30");
 124        }
 125
 2126        if (request.PorcentajeSubsidio.HasValue && (request.PorcentajeSubsidio < 0 || request.PorcentajeSubsidio > 100))
 127        {
 0128            return (false, null, "El porcentaje de subsidio debe estar entre 0 y 100");
 129        }
 130
 2131        if (request.FechaDesde == default)
 132        {
 0133            return (false, null, "La fecha desde es requerida");
 134        }
 135
 2136        if (request.FechaDesde.Date > DateTime.UtcNow.Date)
 137        {
 0138            return (false, null, "La fecha desde no puede ser futura");
 139        }
 140
 2141        var periodo = await _periodosRepository.ObtenerPorIdAsync(request.PeriodoId);
 2142        if (periodo == null)
 143        {
 1144            return (false, null, "Periodo no encontrado");
 145        }
 146
 1147        var relacion = await _personalRepository.GetActivoByPersonaIdAsync(request.PersonaId);
 1148        if (relacion == null)
 149        {
 0150            return (false, null, "Persona no encontrada o no tiene relación laboral activa");
 151        }
 152
 1153        if (await _novedadPeriodoRepository.ExistsAsync(request.PeriodoId, request.PersonaId, request.Tipo, request.Fech
 154        {
 0155            return (false, null, "Ya existe una novedad de período con el mismo tipo y fecha para esta persona y período
 156        }
 157
 1158        var entidad = new NovedadPeriodo
 1159        {
 1160            PeriodoId = request.PeriodoId,
 1161            PersonaId = request.PersonaId,
 1162            Tipo = request.Tipo.Trim(),
 1163            DiasAfectados = request.DiasAfectados,
 1164            PorcentajeSubsidio = request.PorcentajeSubsidio,
 1165            FechaDesde = request.FechaDesde.Date,
 1166            Observaciones = string.IsNullOrWhiteSpace(request.Observaciones) ? null : request.Observaciones.Trim(),
 1167            Estado = "borrador",
 1168            CreadoPor = _currentUser.UserId,
 1169            CreadoEn = DateTime.UtcNow
 1170        };
 171
 1172        var creado = await _novedadPeriodoRepository.CreateAsync(entidad);
 173
 1174        await _auditoriaService.LogAuditoriaAsync(
 1175            usuarioId: _currentUser.UserId ?? 0,
 1176            AccionEnum.CrearNovedad,
 1177            ContextoEnum.Novedades,
 1178            host: _currentUser.Host,
 1179            entidad: nameof(NovedadPeriodo),
 1180            entidadId: creado.Id,
 1181            detalle: new
 1182            {
 1183                operacion = "crear",
 1184                periodoId = creado.PeriodoId,
 1185                personaId = creado.PersonaId,
 1186                tipo = creado.Tipo,
 1187                diasAfectados = creado.DiasAfectados,
 1188                porcentajeSubsidio = creado.PorcentajeSubsidio,
 1189                fechaDesde = creado.FechaDesde,
 1190                estado = creado.Estado
 1191            });
 192
 1193        return (true, creado, null);
 2194    }
 195
 196    public async Task<(bool Success, NovedadPeriodo? Result, string? Error)> UpdateAsync(long id, ActualizarNovedadPerio
 197    {
 0198        if (request == null)
 199        {
 0200            return (false, null, "La solicitud de actualización es obligatoria");
 201        }
 202
 0203        var novedad = await _novedadPeriodoRepository.GetByIdAsync(id);
 0204        if (novedad == null || novedad.Estado == "eliminada")
 205        {
 0206            return (false, null, "Novedad de período no encontrada");
 207        }
 208
 0209        if (novedad.Estado != "borrador")
 210        {
 0211            return (false, null, "Solo se pueden actualizar novedades en estado borrador");
 212        }
 213
 0214        if (!request.DiasAfectados.HasValue && !request.PorcentajeSubsidio.HasValue && request.Observaciones is null)
 215        {
 0216            return (false, null, "Debe proporcionar al menos un campo para actualizar");
 217        }
 218
 0219        if (request.DiasAfectados.HasValue && (request.DiasAfectados < 1 || request.DiasAfectados > 30))
 220        {
 0221            return (false, null, "Los días afectados deben estar entre 1 y 30");
 222        }
 223
 0224        if (request.PorcentajeSubsidio.HasValue && (request.PorcentajeSubsidio < 0 || request.PorcentajeSubsidio > 100))
 225        {
 0226            return (false, null, "El porcentaje de subsidio debe estar entre 0 y 100");
 227        }
 228
 0229        var antes = new
 0230        {
 0231            id = novedad.Id,
 0232            diasAfectados = novedad.DiasAfectados,
 0233            porcentajeSubsidio = novedad.PorcentajeSubsidio,
 0234            observaciones = novedad.Observaciones
 0235        };
 236
 0237        if (request.DiasAfectados.HasValue)
 238        {
 0239            novedad.DiasAfectados = request.DiasAfectados.Value;
 240        }
 241
 0242        if (request.PorcentajeSubsidio.HasValue)
 243        {
 0244            novedad.PorcentajeSubsidio = request.PorcentajeSubsidio;
 245        }
 246
 0247        if (request.Observaciones is not null)
 248        {
 0249            novedad.Observaciones = string.IsNullOrWhiteSpace(request.Observaciones) ? null : request.Observaciones.Trim
 250        }
 251
 0252        var actualizado = await _novedadPeriodoRepository.UpdateAsync(novedad);
 253
 0254        await _auditoriaService.LogAuditoriaAsync(
 0255            usuarioId: _currentUser.UserId ?? 0,
 0256            AccionEnum.ActualizarBanco,
 0257            ContextoEnum.Novedades,
 0258            host: _currentUser.Host,
 0259            entidad: nameof(NovedadPeriodo),
 0260            entidadId: actualizado.Id,
 0261            detalle: new { operacion = "actualizar", antes, despues = new { id = actualizado.Id, diasAfectados = actuali
 262
 0263        return (true, actualizado, null);
 0264    }
 265
 266    public async Task<(bool Success, NovedadPeriodo? Result, string? Error)> ChangeStateToConfirmedAsync(long id)
 267    {
 1268        var novedad = await _novedadPeriodoRepository.GetByIdAsync(id);
 1269        if (novedad == null || novedad.Estado == "eliminada")
 270        {
 0271            return (false, null, "Novedad de período no encontrada");
 272        }
 273
 1274        if (novedad.Estado != "borrador")
 275        {
 0276            return (false, null, "Solo se puede confirmar una novedad en estado borrador");
 277        }
 278
 1279        novedad.Estado = "confirmada";
 1280        novedad.ConfirmadoPor = _currentUser.UserId;
 1281        novedad.ConfirmadoEn = DateTime.UtcNow;
 282
 1283        var actualizado = await _novedadPeriodoRepository.UpdateAsync(novedad);
 284
 1285        await _auditoriaService.LogAuditoriaAsync(
 1286            usuarioId: _currentUser.UserId ?? 0,
 1287            AccionEnum.ConfirmarNovedad,
 1288            ContextoEnum.Novedades,
 1289            host: _currentUser.Host,
 1290            entidad: nameof(NovedadPeriodo),
 1291            entidadId: actualizado.Id,
 1292            detalle: new { operacion = "confirmar", estado = actualizado.Estado });
 293
 1294        return (true, actualizado, null);
 1295    }
 296
 297    public async Task<(bool Success, NovedadPeriodo? Result, string? Error)> ChangeStateToAppliedAsync(long id)
 298    {
 1299        var novedad = await _novedadPeriodoRepository.GetByIdAsync(id);
 1300        if (novedad == null || novedad.Estado == "eliminada")
 301        {
 0302            return (false, null, "Novedad de período no encontrada");
 303        }
 304
 1305        if (novedad.Estado != "confirmada")
 306        {
 1307            return (false, null, "Solo se puede aplicar una novedad en estado confirmada");
 308        }
 309
 0310        novedad.Estado = "aplicada";
 311
 0312        var actualizado = await _novedadPeriodoRepository.UpdateAsync(novedad);
 313
 0314        await _auditoriaService.LogAuditoriaAsync(
 0315            usuarioId: _currentUser.UserId ?? 0,
 0316            AccionEnum.ConfirmarNovedad,
 0317            ContextoEnum.Novedades,
 0318            host: _currentUser.Host,
 0319            entidad: nameof(NovedadPeriodo),
 0320            entidadId: actualizado.Id,
 0321            detalle: new { operacion = "aplicar", estado = actualizado.Estado });
 322
 0323        return (true, actualizado, null);
 1324    }
 325
 326    public async Task<(bool Success, NovedadPeriodo? Result, string? Error)> DeleteAsync(long id)
 327    {
 0328        var novedad = await _novedadPeriodoRepository.GetByIdAsync(id);
 0329        if (novedad == null || novedad.Estado == "eliminada")
 330        {
 0331            return (false, null, "Novedad de período no encontrada");
 332        }
 333
 0334        if (novedad.Estado != "borrador")
 335        {
 0336            return (false, null, "Solo se pueden eliminar novedades en estado borrador");
 337        }
 338
 0339        novedad.Estado = "eliminada";
 340
 0341        var actualizado = await _novedadPeriodoRepository.UpdateAsync(novedad);
 342
 0343        await _auditoriaService.LogAuditoriaAsync(
 0344            usuarioId: _currentUser.UserId ?? 0,
 0345            AccionEnum.AnularNovedad,
 0346            ContextoEnum.Novedades,
 0347            host: _currentUser.Host,
 0348            entidad: nameof(NovedadPeriodo),
 0349            entidadId: actualizado.Id,
 0350            detalle: new { operacion = "eliminar", estado = actualizado.Estado });
 351
 0352        return (true, actualizado, null);
 0353    }
 354}