< Summary

Information
Class: FAU.DataAccess.Repositories.CompensacionRepository
Assembly: FAU.DataAccess
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.DataAccess/Repositories/CompensacionRepository.cs
Line coverage
50%
Covered lines: 96
Uncovered lines: 93
Coverable lines: 189
Total lines: 321
Line coverage: 50.7%
Branch coverage
35%
Covered branches: 12
Total branches: 34
Branch coverage: 35.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.DataAccess/Repositories/CompensacionRepository.cs

#LineLine coverage
 1using FAU.Entidades;
 2using Microsoft.EntityFrameworkCore;
 3
 4namespace FAU.DataAccess.Repositories;
 5
 6public class CompensacionRepository : ICompensacionRepository
 7{
 8    private readonly ApplicationDbContext _context;
 9
 4810    public CompensacionRepository(ApplicationDbContext context)
 11    {
 4812        _context = context;
 4813    }
 14
 15    // ── Tipos ────────────────────────────────────────────────────────────────
 16
 17    public async Task<IEnumerable<TipoCompensacion>> GetTiposAsync(bool? activo = null)
 18    {
 419        var query = _context.TiposCompensacion.AsQueryable();
 420        if (activo.HasValue)
 221            query = query.Where(t => t.Vigente == activo.Value);
 422        return await query.OrderBy(t => t.Nombre).ToListAsync();
 423    }
 24
 25    public async Task<TipoCompensacion?> GetTipoByIdAsync(long id)
 226        => await _context.TiposCompensacion.FindAsync(id);
 27
 28    public async Task<TipoCompensacion?> GetTipoByCodigoAsync(string codigo)
 229        => await _context.TiposCompensacion.FirstOrDefaultAsync(t => t.Codigo == codigo);
 30
 31    public async Task<TipoCompensacion> CreateTipoAsync(TipoCompensacion tipo)
 32    {
 133        _context.TiposCompensacion.Add(tipo);
 134        await _context.SaveChangesAsync();
 135        return tipo;
 136    }
 37
 38    public async Task<TipoCompensacion> UpdateTipoAsync(TipoCompensacion tipo)
 39    {
 140        _context.TiposCompensacion.Update(tipo);
 141        await _context.SaveChangesAsync();
 142        return tipo;
 143    }
 44
 45    public async Task DeleteTipoAsync(long id)
 46    {
 247        var tipo = await _context.TiposCompensacion.FindAsync(id);
 248        if (tipo != null)
 49        {
 150            _context.TiposCompensacion.Remove(tipo);
 151            await _context.SaveChangesAsync();
 52        }
 253    }
 54
 55    public async Task<bool> TieneConfiguracionesAsync(long tipoId)
 256        => await _context.ConfigCompensaciones.AnyAsync(c => c.TipoCompensacionId == tipoId);
 57
 58    public async Task<bool> TieneLotesAsync(long tipoId)
 259        => await _context.LotesCompensacion.AnyAsync(l => l.TipoCompensacionId == tipoId);
 60
 61    // ── Configs ──────────────────────────────────────────────────────────────
 62
 63    public async Task<IEnumerable<ConfigCompensacion>> GetConfigsAsync(
 64        long? tipoId = null, long? regimenId = null, long? gradoId = null, bool? activo = null)
 65    {
 466        var query = _context.ConfigCompensaciones
 467            .Include(c => c.TipoCompensacion)
 468            .Include(c => c.Regimen)
 469            .Include(c => c.Grado)
 470            .Include(c => c.Escalafon)
 471            .AsQueryable();
 72
 573        if (tipoId.HasValue) query = query.Where(c => c.TipoCompensacionId == tipoId.Value);
 474        if (regimenId.HasValue) query = query.Where(c => c.RegimenId == regimenId.Value);
 475        if (gradoId.HasValue) query = query.Where(c => c.GradoId == gradoId.Value);
 676        if (activo.HasValue) query = query.Where(c => c.Activo == activo.Value);
 77
 478        return await query.OrderBy(c => c.TipoCompensacionId).ThenBy(c => c.VigenteDesde).ToListAsync();
 479    }
 80
 81    public async Task<ConfigCompensacion?> GetConfigByIdAsync(long id)
 282        => await _context.ConfigCompensaciones
 283            .Include(c => c.TipoCompensacion)
 284            .Include(c => c.Regimen)
 285            .Include(c => c.Grado)
 286            .Include(c => c.Escalafon)
 287            .FirstOrDefaultAsync(c => c.Id == id);
 88
 89    public async Task<ConfigCompensacion?> GetConfigVigenteAsync(long tipoId, DateTime periodo)
 90    {
 591        return await _context.ConfigCompensaciones
 592            .Where(c => c.TipoCompensacionId == tipoId
 593                     && c.Activo
 594                     && c.VigenteDesde <= periodo
 595                     && (c.VigenteHasta == null || c.VigenteHasta >= periodo))
 596            .OrderByDescending(c => c.VigenteDesde)
 597            .FirstOrDefaultAsync();
 598    }
 99
 100    public async Task<bool> EsUnicaConfigActivaAsync(long configId, long tipoId)
 2101        => !await _context.ConfigCompensaciones
 2102            .AnyAsync(c => c.TipoCompensacionId == tipoId && c.Activo && c.Id != configId);
 103
 104    public async Task DesactivarConfigsActivasAsync(long tipoId)
 105    {
 1106        await _context.ConfigCompensaciones
 1107            .Where(c => c.TipoCompensacionId == tipoId && c.Activo)
 1108            .ExecuteUpdateAsync(s => s.SetProperty(c => c.Activo, false));
 0109    }
 110
 111    public async Task<ConfigCompensacion> CreateConfigAsync(ConfigCompensacion config)
 112    {
 1113        _context.ConfigCompensaciones.Add(config);
 1114        await _context.SaveChangesAsync();
 1115        return config;
 1116    }
 117
 118    public async Task<ConfigCompensacion> UpdateConfigAsync(ConfigCompensacion config)
 119    {
 0120        _context.ConfigCompensaciones.Update(config);
 0121        await _context.SaveChangesAsync();
 0122        return config;
 0123    }
 124
 125    public async Task DeleteConfigAsync(long id)
 126    {
 1127        var config = await _context.ConfigCompensaciones.FindAsync(id);
 1128        if (config != null)
 129        {
 1130            _context.ConfigCompensaciones.Remove(config);
 1131            await _context.SaveChangesAsync();
 132        }
 1133    }
 134
 135    // ── Lotes ────────────────────────────────────────────────────────────────
 136
 137    public async Task<(IEnumerable<LoteCompensacion> Items, int TotalCount)> GetLotesPagedAsync(
 138        int page, int pageSize, long? tipoId = null, int? anio = null, int? mes = null, string? estado = null)
 139    {
 0140        var query = _context.LotesCompensacion
 0141            .Include(l => l.TipoCompensacion)
 0142            .Include(l => l.AprobadorUsuario)
 0143            .AsQueryable();
 144
 0145        if (tipoId.HasValue) query = query.Where(l => l.TipoCompensacionId == tipoId.Value);
 0146        if (anio.HasValue) query = query.Where(l => l.Periodo.Year == anio.Value);
 0147        if (mes.HasValue) query = query.Where(l => l.Periodo.Month == mes.Value);
 0148        if (!string.IsNullOrWhiteSpace(estado)) query = query.Where(l => l.Estado == estado);
 149
 0150        var totalCount = await query.CountAsync();
 0151        var items = await query
 0152            .OrderByDescending(l => l.Periodo)
 0153            .ThenBy(l => l.TipoCompensacionId)
 0154            .Skip((page - 1) * pageSize)
 0155            .Take(pageSize)
 0156            .ToListAsync();
 157
 158        // Batch count de items sin cargar los items completos
 0159        var ids = items.Select(l => l.Id).ToList();
 0160        var conteos = await _context.ItemsLoteCompensacion
 0161            .Where(i => ids.Contains(i.LoteCompensacionId))
 0162            .GroupBy(i => i.LoteCompensacionId)
 0163            .Select(g => new { LoteId = g.Key, Count = g.Count() })
 0164            .ToDictionaryAsync(x => x.LoteId, x => x.Count);
 165
 0166        foreach (var lote in items)
 0167            lote.ItemCount = conteos.TryGetValue(lote.Id, out var c) ? c : 0;
 168
 0169        return (items, totalCount);
 0170    }
 171
 172    public async Task<LoteCompensacion?> GetLoteByIdWithItemsAsync(long id)
 0173        => await _context.LotesCompensacion
 0174            .Include(l => l.TipoCompensacion)
 0175            .Include(l => l.AprobadorUsuario)
 0176            .Include(l => l.Items)
 0177                .ThenInclude(i => i.Persona)
 0178            .Include(l => l.Items)
 0179                .ThenInclude(i => i.SnapshotGrado)
 0180            .Include(l => l.Items)
 0181                .ThenInclude(i => i.SnapshotSituacion)
 0182            .Include(l => l.Items)
 0183                .ThenInclude(i => i.SnapshotUnidad)
 0184            .FirstOrDefaultAsync(l => l.Id == id);
 185
 186    public async Task<LoteCompensacion?> GetLoteByIdAsync(long id)
 0187        => await _context.LotesCompensacion.FindAsync(id);
 188
 189    public async Task<bool> ExisteLoteActivoAsync(long tipoId, DateTime periodo)
 4190        => await _context.LotesCompensacion.AnyAsync(l =>
 4191            l.TipoCompensacionId == tipoId &&
 4192            l.Periodo.Year == periodo.Year &&
 4193            l.Periodo.Month == periodo.Month &&
 4194            l.Estado != "rechazado");
 195
 196    public async Task<LoteCompensacion> CreateLoteAsync(LoteCompensacion lote)
 197    {
 1198        _context.LotesCompensacion.Add(lote);
 1199        await _context.SaveChangesAsync();
 1200        return lote;
 1201    }
 202
 203    public async Task<LoteCompensacion> UpdateLoteAsync(LoteCompensacion lote)
 204    {
 205        // Marcar solo propiedades editables como modificadas para evitar problemas con DateTime Kind
 0206        var entry = _context.Entry(lote);
 207
 208        // Solo marcar como modificado si el valor es diferente del original
 0209        if (entry.Property(x => x.Estado).CurrentValue != entry.Property(x => x.Estado).OriginalValue)
 0210            entry.Property(x => x.Estado).IsModified = true;
 211
 0212        if (entry.Property(x => x.Fuente).CurrentValue != entry.Property(x => x.Fuente).OriginalValue)
 0213            entry.Property(x => x.Fuente).IsModified = true;
 214
 0215        if (entry.Property(x => x.NombreArchivo).CurrentValue != entry.Property(x => x.NombreArchivo).OriginalValue)
 0216            entry.Property(x => x.NombreArchivo).IsModified = true;
 217
 0218        if (entry.Property(x => x.HashArchivo).CurrentValue != entry.Property(x => x.HashArchivo).OriginalValue)
 0219            entry.Property(x => x.HashArchivo).IsModified = true;
 220
 0221        await _context.SaveChangesAsync();
 0222        return lote;
 0223    }
 224
 225    public async Task DeleteLoteAsync(LoteCompensacion lote)
 226    {
 0227        _context.LotesCompensacion.Remove(lote);
 0228        await _context.SaveChangesAsync();
 0229    }
 230
 231    public async Task DeleteAllItemsAsync(long loteId)
 232    {
 1233        var items = await _context.ItemsLoteCompensacion
 1234            .Where(i => i.LoteCompensacionId == loteId)
 1235            .ToListAsync();
 1236        _context.ItemsLoteCompensacion.RemoveRange(items);
 1237        await _context.SaveChangesAsync();
 1238    }
 239
 240    // ── Items ────────────────────────────────────────────────────────────────
 241
 242    public async Task<(IEnumerable<ItemLoteCompensacion> Items, int TotalCount)> GetItemsPagedAsync(
 243        long loteId, int page, int pageSize)
 244    {
 0245        var query = _context.ItemsLoteCompensacion
 0246            .Include(i => i.Persona)
 0247            .Include(i => i.SnapshotGrado)
 0248            .Include(i => i.SnapshotSituacion)
 0249            .Include(i => i.SnapshotUnidad)
 0250            .Where(i => i.LoteCompensacionId == loteId);
 251
 0252        var totalCount = await query.CountAsync();
 0253        var items = await query
 0254            .OrderBy(i => i.Id)
 0255            .Skip((page - 1) * pageSize)
 0256            .Take(pageSize)
 0257            .ToListAsync();
 258
 0259        return (items, totalCount);
 0260    }
 261
 262    public async Task<ItemLoteCompensacion?> GetItemByIdAsync(long id)
 2263        => await _context.ItemsLoteCompensacion
 2264            .Include(i => i.Persona)
 2265            .FirstOrDefaultAsync(i => i.Id == id);
 266
 267    public async Task<bool> ExistePersonaEnLoteAsync(long loteId, long personaId)
 2268        => await _context.ItemsLoteCompensacion
 2269            .AnyAsync(i => i.LoteCompensacionId == loteId && i.PersonaId == personaId);
 270
 271    public async Task<decimal> GetMontoTotalItemsAsync(long loteId)
 3272        => await _context.ItemsLoteCompensacion
 3273            .Where(i => i.LoteCompensacionId == loteId)
 3274            .SumAsync(i => i.Monto ?? 0m);
 275
 276    public async Task<int> GetItemCountAsync(long loteId)
 2277        => await _context.ItemsLoteCompensacion
 2278            .CountAsync(i => i.LoteCompensacionId == loteId);
 279
 280    public async Task<int> GetItemsEnErrorCountAsync(long loteId)
 2281        => await _context.ItemsLoteCompensacion
 2282            .CountAsync(i => i.LoteCompensacionId == loteId && i.Estado == "error");
 283
 284    public async Task<TarifaPorCategoria?> GetTarifaCategoriaAsync(long catalogoItemId, string categoria, DateTime perio
 0285        => await _context.TarifasPorCategoria
 0286            .Where(t => t.ItemId == catalogoItemId
 0287                     && t.Categoria == categoria
 0288                     && t.VigenteDesde <= periodo
 0289                     && (t.VigenteHasta == null || t.VigenteHasta >= periodo))
 0290            .OrderByDescending(t => t.VigenteDesde)
 0291            .FirstOrDefaultAsync();
 292
 293    public async Task<RemuneracionGrado?> GetTarifaGradoAsync(long catalogoItemId, long gradoId, DateTime periodo)
 0294        => await _context.RemuneracionesGrado
 0295            .Where(r => r.ItemId == catalogoItemId
 0296                     && r.GradoId == gradoId
 0297                     && r.VigenteDesde <= periodo
 0298                     && (r.VigenteHasta == null || r.VigenteHasta >= periodo))
 0299            .OrderByDescending(r => r.VigenteDesde)
 0300            .FirstOrDefaultAsync();
 301
 302    public async Task<ItemLoteCompensacion> CreateItemAsync(ItemLoteCompensacion item)
 303    {
 1304        _context.ItemsLoteCompensacion.Add(item);
 1305        await _context.SaveChangesAsync();
 1306        return item;
 1307    }
 308
 309    public async Task<ItemLoteCompensacion> UpdateItemAsync(ItemLoteCompensacion item)
 310    {
 0311        _context.ItemsLoteCompensacion.Update(item);
 0312        await _context.SaveChangesAsync();
 0313        return item;
 0314    }
 315
 316    public async Task DeleteItemAsync(ItemLoteCompensacion item)
 317    {
 0318        _context.ItemsLoteCompensacion.Remove(item);
 0319        await _context.SaveChangesAsync();
 0320    }
 321}