< 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
48%
Covered lines: 95
Uncovered lines: 100
Coverable lines: 195
Total lines: 329
Line coverage: 48.7%
Branch coverage
30%
Covered branches: 12
Total branches: 40
Branch coverage: 30%
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, long? periodoId = null, string? estado = null)
 139    {
 0140        var query = _context.LotesCompensacion
 0141            .Include(l => l.TipoCompensacion)
 0142            .Include(l => l.Periodo)
 0143            .Include(l => l.AprobadorUsuario)
 0144            .AsQueryable();
 145
 0146        if (tipoId.HasValue)    query = query.Where(l => l.TipoCompensacionId == tipoId.Value);
 0147        if (periodoId.HasValue) query = query.Where(l => l.PeriodoId == periodoId.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.PeriodoId)
 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.Periodo)
 0175            .Include(l => l.TipoCompensacion)
 0176            .Include(l => l.AprobadorUsuario)
 0177            .Include(l => l.Items)
 0178                .ThenInclude(i => i.Persona)
 0179            .Include(l => l.Items)
 0180                .ThenInclude(i => i.SnapshotGrado)
 0181            .Include(l => l.Items)
 0182                .ThenInclude(i => i.SnapshotSituacion)
 0183            .Include(l => l.Items)
 0184                .ThenInclude(i => i.SnapshotUnidad)
 0185            .FirstOrDefaultAsync(l => l.Id == id);
 186
 187    public async Task<LoteCompensacion?> GetLoteByIdAsync(long id)
 0188        => await _context.LotesCompensacion
 0189            .Include(l => l.Periodo)
 0190            .FirstOrDefaultAsync(l => l.Id == id);
 191
 192    public async Task<bool> ExisteLoteActivoAsync(long tipoId, long periodoId)
 4193        => await _context.LotesCompensacion.AnyAsync(l =>
 4194            l.TipoCompensacionId == tipoId &&
 4195            l.PeriodoId == periodoId &&
 4196            l.Estado != "rechazado");
 197
 198    public async Task<LoteCompensacion> CreateLoteAsync(LoteCompensacion lote)
 199    {
 1200        _context.LotesCompensacion.Add(lote);
 1201        await _context.SaveChangesAsync();
 1202        return lote;
 1203    }
 204
 205    public async Task<LoteCompensacion> UpdateLoteAsync(LoteCompensacion lote)
 206    {
 207        // Marcar solo propiedades editables como modificadas para evitar problemas con DateTime Kind
 0208        var entry = _context.Entry(lote);
 209
 210        // Solo marcar como modificado si el valor es diferente del original
 0211        if (entry.Property(x => x.Estado).CurrentValue != entry.Property(x => x.Estado).OriginalValue)
 0212            entry.Property(x => x.Estado).IsModified = true;
 213
 0214        if (entry.Property(x => x.Fuente).CurrentValue != entry.Property(x => x.Fuente).OriginalValue)
 0215            entry.Property(x => x.Fuente).IsModified = true;
 216
 0217        if (entry.Property(x => x.NombreArchivo).CurrentValue != entry.Property(x => x.NombreArchivo).OriginalValue)
 0218            entry.Property(x => x.NombreArchivo).IsModified = true;
 219
 0220        if (entry.Property(x => x.HashArchivo).CurrentValue != entry.Property(x => x.HashArchivo).OriginalValue)
 0221            entry.Property(x => x.HashArchivo).IsModified = true;
 222
 0223        if (entry.Property(x => x.AprobadoPor).CurrentValue != entry.Property(x => x.AprobadoPor).OriginalValue)
 0224            entry.Property(x => x.AprobadoPor).IsModified = true;
 225
 0226        if (entry.Property(x => x.AprobadoEn).CurrentValue != entry.Property(x => x.AprobadoEn).OriginalValue)
 0227            entry.Property(x => x.AprobadoEn).IsModified = true;
 228
 0229        await _context.SaveChangesAsync();
 0230        return lote;
 0231    }
 232
 233    public async Task DeleteLoteAsync(LoteCompensacion lote)
 234    {
 0235        _context.LotesCompensacion.Remove(lote);
 0236        await _context.SaveChangesAsync();
 0237    }
 238
 239    public async Task DeleteAllItemsAsync(long loteId)
 240    {
 1241        var items = await _context.ItemsLoteCompensacion
 1242            .Where(i => i.LoteCompensacionId == loteId)
 1243            .ToListAsync();
 1244        _context.ItemsLoteCompensacion.RemoveRange(items);
 1245        await _context.SaveChangesAsync();
 1246    }
 247
 248    // ── Items ────────────────────────────────────────────────────────────────
 249
 250    public async Task<(IEnumerable<ItemLoteCompensacion> Items, int TotalCount)> GetItemsPagedAsync(
 251        long loteId, int page, int pageSize)
 252    {
 0253        var query = _context.ItemsLoteCompensacion
 0254            .Include(i => i.Persona)
 0255            .Include(i => i.SnapshotGrado)
 0256            .Include(i => i.SnapshotSituacion)
 0257            .Include(i => i.SnapshotUnidad)
 0258            .Where(i => i.LoteCompensacionId == loteId);
 259
 0260        var totalCount = await query.CountAsync();
 0261        var items = await query
 0262            .OrderBy(i => i.Id)
 0263            .Skip((page - 1) * pageSize)
 0264            .Take(pageSize)
 0265            .ToListAsync();
 266
 0267        return (items, totalCount);
 0268    }
 269
 270    public async Task<ItemLoteCompensacion?> GetItemByIdAsync(long id)
 2271        => await _context.ItemsLoteCompensacion
 2272            .Include(i => i.Persona)
 2273            .FirstOrDefaultAsync(i => i.Id == id);
 274
 275    public async Task<bool> ExistePersonaEnLoteAsync(long loteId, long personaId)
 2276        => await _context.ItemsLoteCompensacion
 2277            .AnyAsync(i => i.LoteCompensacionId == loteId && i.PersonaId == personaId);
 278
 279    public async Task<decimal> GetMontoTotalItemsAsync(long loteId)
 3280        => await _context.ItemsLoteCompensacion
 3281            .Where(i => i.LoteCompensacionId == loteId)
 3282            .SumAsync(i => i.Monto ?? 0m);
 283
 284    public async Task<int> GetItemCountAsync(long loteId)
 2285        => await _context.ItemsLoteCompensacion
 2286            .CountAsync(i => i.LoteCompensacionId == loteId);
 287
 288    public async Task<int> GetItemsEnErrorCountAsync(long loteId)
 2289        => await _context.ItemsLoteCompensacion
 2290            .CountAsync(i => i.LoteCompensacionId == loteId && i.Estado == "error");
 291
 292    public async Task<TarifaPorCategoria?> GetTarifaCategoriaAsync(long catalogoItemId, string categoria, DateTime perio
 0293        => await _context.TarifasPorCategoria
 0294            .Where(t => t.ItemId == catalogoItemId
 0295                     && t.Categoria == categoria
 0296                     && t.VigenteDesde <= periodo
 0297                     && (t.VigenteHasta == null || t.VigenteHasta >= periodo))
 0298            .OrderByDescending(t => t.VigenteDesde)
 0299            .FirstOrDefaultAsync();
 300
 301    public async Task<RemuneracionGrado?> GetTarifaGradoAsync(long catalogoItemId, long gradoId, DateTime periodo)
 0302        => await _context.RemuneracionesGrado
 0303            .Where(r => r.ItemId == catalogoItemId
 0304                     && r.GradoId == gradoId
 0305                     && r.VigenteDesde <= periodo
 0306                     && (r.VigenteHasta == null || r.VigenteHasta >= periodo))
 0307            .OrderByDescending(r => r.VigenteDesde)
 0308            .FirstOrDefaultAsync();
 309
 310    public async Task<ItemLoteCompensacion> CreateItemAsync(ItemLoteCompensacion item)
 311    {
 1312        _context.ItemsLoteCompensacion.Add(item);
 1313        await _context.SaveChangesAsync();
 1314        return item;
 1315    }
 316
 317    public async Task<ItemLoteCompensacion> UpdateItemAsync(ItemLoteCompensacion item)
 318    {
 0319        _context.ItemsLoteCompensacion.Update(item);
 0320        await _context.SaveChangesAsync();
 0321        return item;
 0322    }
 323
 324    public async Task DeleteItemAsync(ItemLoteCompensacion item)
 325    {
 0326        _context.ItemsLoteCompensacion.Remove(item);
 0327        await _context.SaveChangesAsync();
 0328    }
 329}