< Summary

Information
Class: FAU.Logica.Services.BeneficioSocialBeneficiarioService
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/BeneficioSocialBeneficiarioService.cs
Line coverage
99%
Covered lines: 124
Uncovered lines: 1
Coverable lines: 125
Total lines: 196
Line coverage: 99.2%
Branch coverage
85%
Covered branches: 48
Total branches: 56
Branch coverage: 85.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ObtenerPorBeneficioAsync()100%22100%
ObtenerPorIdAsync()50%22100%
AgregarAsync()85.71%1414100%
ActualizarAsync()85%2020100%
EliminarAsync()100%22100%
SubirDocumentoAsync()75%44100%
ObtenerDocumentosAsync()100%22100%
DescargarDocumentoAsync()100%44100%
EliminarDocumentoAsync()100%4487.5%
MapDto(...)50%22100%

File(s)

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

#LineLine coverage
 1using FAU.DataAccess.Repositories;
 2using FAU.Entidades;
 3using FAU.Logica.DTOs;
 4
 5namespace FAU.Logica.Services;
 6
 7public class BeneficioSocialBeneficiarioService : IBeneficioSocialBeneficiarioService
 8{
 9    private readonly IBeneficioSocialBeneficiarioRepository _repo;
 10    private readonly IBeneficioSocialRepository _beneficioRepo;
 11    private readonly IDocumentoRepository _docRepo;
 12    private readonly IStorageService _storage;
 13
 2414    public BeneficioSocialBeneficiarioService(
 2415        IBeneficioSocialBeneficiarioRepository repo,
 2416        IBeneficioSocialRepository beneficioRepo,
 2417        IDocumentoRepository docRepo,
 2418        IStorageService storage)
 19    {
 2420        _repo        = repo;
 2421        _beneficioRepo = beneficioRepo;
 2422        _docRepo     = docRepo;
 2423        _storage     = storage;
 2424    }
 25
 26    public async Task<IReadOnlyList<BeneficiarioSocialDto>> ObtenerPorBeneficioAsync(
 27        long beneficioId, bool soloActivos = true)
 28    {
 129        var beneficiarios = await _repo.ObtenerPorBeneficioAsync(beneficioId, soloActivos);
 130        return beneficiarios.Select(MapDto).ToList();
 131    }
 32
 33    public async Task<BeneficiarioSocialDto?> ObtenerPorIdAsync(long id)
 34    {
 235        var entidad = await _repo.ObtenerPorIdAsync(id);
 236        return entidad is null ? null : MapDto(entidad);
 237    }
 38
 39    public async Task<BeneficiarioSocialDto> AgregarAsync(
 40        long beneficioId, CrearBeneficiarioSocialRequest request, long usuarioId)
 41    {
 642        var beneficio = await _beneficioRepo.ObtenerPorIdAsync(beneficioId)
 643            ?? throw new ArgumentException($"Beneficio social {beneficioId} no encontrado.");
 44
 545        if (beneficio.Estado != "activo")
 146            throw new InvalidOperationException("Solo se pueden agregar beneficiarios a beneficios activos.");
 47
 448        if (request.VigenteHasta.HasValue && request.VigenteHasta.Value.Date < request.VigenteDesde.Date)
 149            throw new ArgumentException("La vigencia hasta no puede ser anterior a la vigencia desde.");
 50
 351        if (request.FechaNacimiento.Date > DateTime.Now.Date)
 152            throw new ArgumentException("La fecha de nacimiento no puede ser futura.");
 53
 254        var entidad = new BeneficioSocialBeneficiario
 255        {
 256            BeneficioId      = beneficioId,
 257            Nombre           = request.Nombre.Trim(),
 258            Apellido         = request.Apellido.Trim(),
 259            Cedula           = request.Cedula?.Trim(),
 260            FechaNacimiento  = request.FechaNacimiento.Date,
 261            Discapacidad     = request.Discapacidad,
 262            VigenteDesde     = request.VigenteDesde.Date,
 263            VigenteHasta     = request.VigenteHasta?.Date,
 264            Activo           = true,
 265            CreadoPor        = usuarioId,
 266            CreadoEn         = DateTime.Now
 267        };
 68
 269        var creado = await _repo.CrearAsync(entidad);
 270        return MapDto(creado);
 271    }
 72
 73    public async Task<BeneficiarioSocialDto> ActualizarAsync(
 74        long id, ActualizarBeneficiarioSocialRequest request)
 75    {
 376        var entidad = await _repo.ObtenerPorIdAsync(id)
 377            ?? throw new ArgumentException($"Beneficiario {id} no encontrado.");
 78
 379        if (request.Nombre is not null)         entidad.Nombre          = request.Nombre.Trim();
 280        if (request.Apellido is not null)        entidad.Apellido        = request.Apellido.Trim();
 281        if (request.Cedula is not null)          entidad.Cedula          = request.Cedula.Trim();
 282        if (request.FechaNacimiento.HasValue)    entidad.FechaNacimiento = request.FechaNacimiento.Value.Date;
 383        if (request.Discapacidad.HasValue)       entidad.Discapacidad    = request.Discapacidad.Value;
 384        if (request.VigenteDesde.HasValue)       entidad.VigenteDesde    = request.VigenteDesde.Value.Date;
 385        if (request.VigenteHasta.HasValue)       entidad.VigenteHasta    = request.VigenteHasta.Value.Date;
 86
 287        if (entidad.VigenteHasta.HasValue && entidad.VigenteHasta.Value.Date < entidad.VigenteDesde.Date)
 188            throw new ArgumentException("La vigencia hasta no puede ser anterior a la vigencia desde.");
 89
 190        var actualizado = await _repo.ActualizarAsync(entidad);
 191        return MapDto(actualizado);
 192    }
 93
 94    public async Task EliminarAsync(long id)
 95    {
 296        var entidad = await _repo.ObtenerPorIdAsync(id)
 297            ?? throw new ArgumentException($"Beneficiario {id} no encontrado.");
 198        await _repo.EliminarAsync(entidad.Id);
 199    }
 100
 101    public async Task<string> SubirDocumentoAsync(
 102        long beneficiarioId, Stream contenido, string nombreOriginal,
 103        string contentType, long usuarioId)
 104    {
 2105        var beneficiario = await _repo.ObtenerPorIdAsync(beneficiarioId)
 2106            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 107
 1108        var ext              = Path.GetExtension(nombreOriginal);
 1109        var nombreSanitizado = Path.GetFileNameWithoutExtension(nombreOriginal)
 1110                                   .Replace(" ", "_")
 1111                                   .Replace("..", "") + ext;
 1112        var rutaRelativa = $"asig_fam/beneficiarios/{beneficiarioId}/{nombreSanitizado}";
 1113        var tamanio      = contenido.CanSeek ? contenido.Length : 0;
 114
 1115        await _storage.GuardarAsync(contenido, rutaRelativa, contentType);
 116
 1117        await _docRepo.CreateAsync(new Documento
 1118        {
 1119            Tipo           = "asig_fam_beneficiario",
 1120            EntidadId      = beneficiarioId,
 1121            RutaRelativa   = rutaRelativa,
 1122            NombreOriginal = nombreOriginal,
 1123            ContentType    = contentType,
 1124            TamanioBytes   = tamanio,
 1125            UsuarioCargaId = usuarioId
 1126        });
 127
 1128        return rutaRelativa;
 1129    }
 130
 131    public async Task<IEnumerable<DocumentoDto>> ObtenerDocumentosAsync(long beneficiarioId)
 132    {
 2133        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 2134            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 135
 1136        var docs = await _docRepo.GetByTipoEntidadAsync("asig_fam_beneficiario", beneficiarioId);
 2137        return docs.Select(d => new DocumentoDto
 2138        {
 2139            Id             = d.Id,
 2140            NombreOriginal = d.NombreOriginal,
 2141            ContentType    = d.ContentType,
 2142            TamanioBytes   = d.TamanioBytes,
 2143            FechaCarga     = d.FechaCarga
 2144        });
 1145    }
 146
 147    public async Task<(Stream Contenido, string NombreOriginal, string ContentType)> DescargarDocumentoAsync(
 148        long beneficiarioId, long documentoId)
 149    {
 3150        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 3151            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 152
 2153        var doc = await _docRepo.GetByIdAsync(documentoId)
 2154            ?? throw new KeyNotFoundException($"Documento {documentoId} no encontrado.");
 155
 1156        var stream = await _storage.ObtenerAsync(doc.RutaRelativa);
 1157        return (stream, doc.NombreOriginal, doc.ContentType);
 1158    }
 159
 160    public async Task EliminarDocumentoAsync(long beneficiarioId, long documentoId)
 161    {
 3162        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 3163            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 164
 2165        var doc = await _docRepo.GetByIdAsync(documentoId)
 2166            ?? throw new KeyNotFoundException($"Documento {documentoId} no encontrado.");
 167
 2168        try { await _storage.EliminarAsync(doc.RutaRelativa); }
 0169        catch { /* si el archivo físico ya no existe, igual eliminamos el registro */ }
 170
 1171        await _docRepo.DeleteAsync(documentoId);
 1172    }
 173
 174    private static BeneficiarioSocialDto MapDto(BeneficioSocialBeneficiario e)
 175    {
 6176        var hoy      = DateTime.Now.Date;
 6177        var edad     = hoy.Year - e.FechaNacimiento.Year;
 6178        if (e.FechaNacimiento.Date > hoy.AddYears(-edad)) edad--;
 179
 6180        return new BeneficiarioSocialDto
 6181        {
 6182            Id              = e.Id,
 6183            BeneficioId     = e.BeneficioId,
 6184            Nombre          = e.Nombre,
 6185            Apellido        = e.Apellido,
 6186            Cedula          = e.Cedula,
 6187            FechaNacimiento = e.FechaNacimiento,
 6188            Discapacidad    = e.Discapacidad,
 6189            VigenteDesde    = e.VigenteDesde,
 6190            VigenteHasta    = e.VigenteHasta,
 6191            Activo          = e.Activo,
 6192            EdadAnios       = edad,
 6193            EsMenorDeEdad   = edad < 18
 6194        };
 195    }
 196}