< Summary

Information
Class: FAU.Logica.Services.Form3100Service
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/Form3100Service.cs
Line coverage
53%
Covered lines: 42
Uncovered lines: 37
Coverable lines: 79
Total lines: 141
Line coverage: 53.1%
Branch coverage
43%
Covered branches: 14
Total branches: 32
Branch coverage: 43.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%
CrearAsync()100%44100%
GetHistorialAsync()100%22100%
GetVigenteParaPeriodoAsync()100%22100%
GetByIdAsync(...)100%210%
AgregarPersonaACargoAsync()75%44100%
EliminarPersonaACargoAsync()75%44100%
SubirArchivoAsync()0%7280%
ObtenerArchivoAsync()0%4260%
SanitizarNombre(...)0%620%

File(s)

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

#LineLine coverage
 1using FAU.DataAccess.Repositories;
 2using FAU.Entidades;
 3
 4namespace FAU.Logica.Services;
 5
 6public class Form3100Service : IForm3100Service
 7{
 8    private readonly IForm3100Repository _repo;
 9    private readonly IPersonalRepository _personalRepo;
 10    private readonly IDocumentoRepository _docRepo;
 11    private readonly IStorageService _storage;
 12
 1113    public Form3100Service(
 1114        IForm3100Repository repo,
 1115        IPersonalRepository personalRepo,
 1116        IDocumentoRepository docRepo,
 1117        IStorageService storage)
 18    {
 1119        _repo        = repo;
 1120        _personalRepo = personalRepo;
 1121        _docRepo     = docRepo;
 1122        _storage     = storage;
 1123    }
 24
 25    public async Task<Form3100> CrearAsync(string cedulaTitular, Form3100 form, long usuarioId)
 26    {
 327        var relacion = await _personalRepo.GetByCedulaAsync(cedulaTitular)
 328            ?? throw new ArgumentException($"Funcionario con cédula {cedulaTitular} no encontrado.");
 29
 230        var personaId = relacion.PersonaId;
 31
 232        if (await _repo.ExisteVigenciaAsync(personaId, form.VigenteDesde_Anio, form.VigenteDesde_Mes))
 133            throw new InvalidOperationException(
 134                $"Ya existe un formulario para {cedulaTitular} con vigencia {form.VigenteDesde_Mes:D2}/{form.VigenteDesd
 35
 136        form.PersonaId          = personaId;
 137        form.UsuarioCreacionId  = usuarioId;
 138        form.FechaCreacion      = DateTime.UtcNow;
 39
 140        return await _repo.CreateAsync(form);
 141    }
 42
 43    public async Task<IEnumerable<Form3100>> GetHistorialAsync(string cedulaTitular, int? anio = null, int? mes = null)
 44    {
 245        var relacion = await _personalRepo.GetByCedulaAsync(cedulaTitular);
 346        if (relacion == null) return Enumerable.Empty<Form3100>();
 147        return await _repo.GetHistorialAsync(relacion.PersonaId, anio, mes);
 248    }
 49
 50    public async Task<Form3100?> GetVigenteParaPeriodoAsync(string cedulaTitular, int anio, int mes)
 51    {
 252        var relacion = await _personalRepo.GetByCedulaAsync(cedulaTitular);
 353        if (relacion == null) return null;
 154        return await _repo.GetVigenteParaPeriodoAsync(relacion.PersonaId, anio, mes);
 255    }
 56
 057    public Task<Form3100?> GetByIdAsync(long id) => _repo.GetByIdAsync(id);
 58
 59    public async Task<Form3100PersonaACargo> AgregarPersonaACargoAsync(long form3100Id, Form3100PersonaACargo persona)
 60    {
 261        var form = await _repo.GetByIdAsync(form3100Id)
 262            ?? throw new ArgumentException($"Form3100 {form3100Id} no encontrado.");
 63
 264        if (!new[] { 0, 50, 100 }.Contains((int)persona.PorcentajeAtribucion))
 165            throw new ArgumentException("PorcentajeAtribucion debe ser 0, 50 o 100.");
 66
 167        persona.Form3100Id = form3100Id;
 168        return await _repo.AddPersonaACargoAsync(persona);
 169    }
 70
 71    public async Task EliminarPersonaACargoAsync(long form3100Id, long personaCargoId)
 72    {
 273        var p = await _repo.GetPersonaACargoAsync(personaCargoId)
 274            ?? throw new ArgumentException($"Persona a cargo {personaCargoId} no encontrada.");
 75
 276        if (p.Form3100Id != form3100Id)
 177            throw new ArgumentException("La persona a cargo no pertenece al formulario indicado.");
 78
 179        await _repo.DeletePersonaACargoAsync(personaCargoId);
 180    }
 81
 82    public async Task<string> SubirArchivoAsync(long form3100Id, Stream contenido, string nombreOriginal, string content
 83    {
 084        var form = await _repo.GetByIdAsync(form3100Id)
 085            ?? throw new ArgumentException($"Form3100 {form3100Id} no encontrado.");
 86
 087        var nombreSanitizado = SanitizarNombre(nombreOriginal);
 088        var rutaRelativa     = $"form3100/{form3100Id}/{nombreSanitizado}";
 89
 90        // Eliminar archivo anterior si existe
 091        if (form.DocumentoId.HasValue)
 92        {
 093            var docAnterior = await _docRepo.GetByIdAsync(form.DocumentoId.Value);
 094            if (docAnterior != null)
 95            {
 096                await _storage.EliminarAsync(docAnterior.RutaRelativa);
 097                await _docRepo.DeleteAsync(docAnterior.Id);
 98            }
 099        }
 100
 101        // Obtener tamaño
 0102        var tamanio = contenido.CanSeek ? contenido.Length : 0;
 103
 0104        await _storage.GuardarAsync(contenido, rutaRelativa, contentType);
 105
 0106        var documento = await _docRepo.CreateAsync(new Documento
 0107        {
 0108            Tipo            = "form3100",
 0109            EntidadId       = form3100Id,
 0110            RutaRelativa    = rutaRelativa,
 0111            NombreOriginal  = nombreOriginal,
 0112            ContentType     = contentType,
 0113            TamanioBytes    = tamanio,
 0114            UsuarioCargaId  = usuarioId
 0115        });
 116
 0117        form.DocumentoId = documento.Id;
 0118        await _repo.UpdateAsync(form);
 119
 0120        return rutaRelativa;
 0121    }
 122
 123    public async Task<(Stream Contenido, string NombreOriginal, string ContentType)> ObtenerArchivoAsync(long form3100Id
 124    {
 0125        var form = await _repo.GetByIdAsync(form3100Id)
 0126            ?? throw new ArgumentException($"Form3100 {form3100Id} no encontrado.");
 127
 0128        if (!form.DocumentoId.HasValue || form.Documento == null)
 0129            throw new KeyNotFoundException($"Form3100 {form3100Id} no tiene archivo adjunto.");
 130
 0131        var stream = await _storage.ObtenerAsync(form.Documento.RutaRelativa);
 0132        return (stream, form.Documento.NombreOriginal, form.Documento.ContentType);
 0133    }
 134
 135    private static string SanitizarNombre(string nombre)
 136    {
 0137        var invalidos = Path.GetInvalidFileNameChars();
 0138        var limpio    = string.Concat(nombre.Select(c => invalidos.Contains(c) ? '_' : c));
 0139        return limpio.Replace(' ', '_').ToLower();
 140    }
 141}