< 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
64%
Covered lines: 81
Uncovered lines: 44
Coverable lines: 125
Total lines: 196
Line coverage: 64.8%
Branch coverage
32%
Covered branches: 18
Total branches: 56
Branch coverage: 32.1%
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()0%620%
ObtenerPorIdAsync()50%22100%
AgregarAsync()85.71%1414100%
ActualizarAsync()0%420200%
EliminarAsync()100%22100%
SubirDocumentoAsync()50%44100%
ObtenerDocumentosAsync()0%620%
DescargarDocumentoAsync()0%2040%
EliminarDocumentoAsync()0%2040%
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
 1114    public BeneficioSocialBeneficiarioService(
 1115        IBeneficioSocialBeneficiarioRepository repo,
 1116        IBeneficioSocialRepository beneficioRepo,
 1117        IDocumentoRepository docRepo,
 1118        IStorageService storage)
 19    {
 1120        _repo        = repo;
 1121        _beneficioRepo = beneficioRepo;
 1122        _docRepo     = docRepo;
 1123        _storage     = storage;
 1124    }
 25
 26    public async Task<IReadOnlyList<BeneficiarioSocialDto>> ObtenerPorBeneficioAsync(
 27        long beneficioId, bool soloActivos = true)
 28    {
 029        var beneficiarios = await _repo.ObtenerPorBeneficioAsync(beneficioId, soloActivos);
 030        return beneficiarios.Select(MapDto).ToList();
 031    }
 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    {
 076        var entidad = await _repo.ObtenerPorIdAsync(id)
 077            ?? throw new ArgumentException($"Beneficiario {id} no encontrado.");
 78
 079        if (request.Nombre is not null)         entidad.Nombre          = request.Nombre.Trim();
 080        if (request.Apellido is not null)        entidad.Apellido        = request.Apellido.Trim();
 081        if (request.Cedula is not null)          entidad.Cedula          = request.Cedula.Trim();
 082        if (request.FechaNacimiento.HasValue)    entidad.FechaNacimiento = request.FechaNacimiento.Value.Date;
 083        if (request.Discapacidad.HasValue)       entidad.Discapacidad    = request.Discapacidad.Value;
 084        if (request.VigenteDesde.HasValue)       entidad.VigenteDesde    = request.VigenteDesde.Value.Date;
 085        if (request.VigenteHasta.HasValue)       entidad.VigenteHasta    = request.VigenteHasta.Value.Date;
 86
 087        if (entidad.VigenteHasta.HasValue && entidad.VigenteHasta.Value.Date < entidad.VigenteDesde.Date)
 088            throw new ArgumentException("La vigencia hasta no puede ser anterior a la vigencia desde.");
 89
 090        var actualizado = await _repo.ActualizarAsync(entidad);
 091        return MapDto(actualizado);
 092    }
 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    {
 1105        var beneficiario = await _repo.ObtenerPorIdAsync(beneficiarioId)
 1106            ?? 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    {
 0133        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 0134            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 135
 0136        var docs = await _docRepo.GetByTipoEntidadAsync("asig_fam_beneficiario", beneficiarioId);
 0137        return docs.Select(d => new DocumentoDto
 0138        {
 0139            Id             = d.Id,
 0140            NombreOriginal = d.NombreOriginal,
 0141            ContentType    = d.ContentType,
 0142            TamanioBytes   = d.TamanioBytes,
 0143            FechaCarga     = d.FechaCarga
 0144        });
 0145    }
 146
 147    public async Task<(Stream Contenido, string NombreOriginal, string ContentType)> DescargarDocumentoAsync(
 148        long beneficiarioId, long documentoId)
 149    {
 0150        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 0151            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 152
 0153        var doc = await _docRepo.GetByIdAsync(documentoId)
 0154            ?? throw new KeyNotFoundException($"Documento {documentoId} no encontrado.");
 155
 0156        var stream = await _storage.ObtenerAsync(doc.RutaRelativa);
 0157        return (stream, doc.NombreOriginal, doc.ContentType);
 0158    }
 159
 160    public async Task EliminarDocumentoAsync(long beneficiarioId, long documentoId)
 161    {
 0162        _ = await _repo.ObtenerPorIdAsync(beneficiarioId)
 0163            ?? throw new ArgumentException($"Beneficiario {beneficiarioId} no encontrado.");
 164
 0165        var doc = await _docRepo.GetByIdAsync(documentoId)
 0166            ?? throw new KeyNotFoundException($"Documento {documentoId} no encontrado.");
 167
 0168        try { await _storage.EliminarAsync(doc.RutaRelativa); }
 0169        catch { /* si el archivo físico ya no existe, igual eliminamos el registro */ }
 170
 0171        await _docRepo.DeleteAsync(documentoId);
 0172    }
 173
 174    private static BeneficiarioSocialDto MapDto(BeneficioSocialBeneficiario e)
 175    {
 4176        var hoy      = DateTime.Now.Date;
 4177        var edad     = hoy.Year - e.FechaNacimiento.Year;
 4178        if (e.FechaNacimiento.Date > hoy.AddYears(-edad)) edad--;
 179
 4180        return new BeneficiarioSocialDto
 4181        {
 4182            Id              = e.Id,
 4183            BeneficioId     = e.BeneficioId,
 4184            Nombre          = e.Nombre,
 4185            Apellido        = e.Apellido,
 4186            Cedula          = e.Cedula,
 4187            FechaNacimiento = e.FechaNacimiento,
 4188            Discapacidad    = e.Discapacidad,
 4189            VigenteDesde    = e.VigenteDesde,
 4190            VigenteHasta    = e.VigenteHasta,
 4191            Activo          = e.Activo,
 4192            EdadAnios       = edad,
 4193            EsMenorDeEdad   = edad < 18
 4194        };
 195    }
 196}