Files
RS_System/RS_system/Services/ContabilidadService.cs
2026-02-01 14:28:17 -06:00

170 lines
6.0 KiB
C#

using Microsoft.EntityFrameworkCore;
using Rs_system.Data;
using Rs_system.Models;
namespace Rs_system.Services;
public class ContabilidadService : IContabilidadService
{
private readonly ApplicationDbContext _context;
public ContabilidadService(ApplicationDbContext context)
{
_context = context;
}
public async Task<ContabilidadRegistro> CrearRegistroAsync(ContabilidadRegistro registro)
{
// Ensure Group exists
var groupExists = await _context.GruposTrabajo.AnyAsync(g => g.Id == registro.GrupoTrabajoId);
if (!groupExists)
{
throw new ArgumentException($"Grupo de trabajo con ID {registro.GrupoTrabajoId} no existe.");
}
_context.ContabilidadRegistros.Add(registro);
await _context.SaveChangesAsync();
return registro;
}
public async Task<IReadOnlyList<ContabilidadRegistro>> ObtenerRegistrosAsync(long grupoId, DateTime desde, DateTime hasta)
{
return await _context.ContabilidadRegistros
.Include(c => c.GrupoTrabajo)
.Where(c => c.GrupoTrabajoId == grupoId && c.Fecha.Date >= desde.Date && c.Fecha.Date <= hasta.Date)
.OrderByDescending(c => c.Fecha)
.ToListAsync();
}
public async Task<ReporteMensualContable?> ObtenerReporteMensualAsync(long grupoId, int mes, int anio)
{
return await _context.ReportesMensualesContables
.Include(r => r.Registros)
.FirstOrDefaultAsync(r => r.GrupoTrabajoId == grupoId && r.Mes == mes && r.Anio == anio);
}
public async Task<ReporteMensualContable> ObtenerOCrearReporteMensualAsync(long grupoId, int mes, int anio)
{
var reporte = await ObtenerReporteMensualAsync(grupoId, mes, anio);
if (reporte != null) return reporte;
// Calculate Saldo Inicial based on previous month
decimal saldoInicial = 0;
var prevMes = mes == 1 ? 12 : mes - 1;
var prevAnio = mes == 1 ? anio - 1 : anio;
var reportePrevio = await ObtenerReporteMensualAsync(grupoId, prevMes, prevAnio);
if (reportePrevio != null)
{
saldoInicial = await CalcularSaldoActualAsync(reportePrevio.Id);
}
reporte = new ReporteMensualContable
{
GrupoTrabajoId = grupoId,
Mes = mes,
Anio = anio,
SaldoInicial = saldoInicial,
FechaCreacion = DateTime.UtcNow,
Cerrado = false
};
_context.ReportesMensualesContables.Add(reporte);
await _context.SaveChangesAsync();
return reporte;
}
public async Task<List<ReporteMensualContable>> ListarReportesPorGrupoAsync(long grupoId)
{
return await _context.ReportesMensualesContables
.Where(r => r.GrupoTrabajoId == grupoId)
.OrderByDescending(r => r.Anio)
.ThenByDescending(r => r.Mes)
.ToListAsync();
}
public async Task<bool> GuardarRegistrosBulkAsync(long reporteId, List<ContabilidadRegistro> registros)
{
var reporte = await _context.ReportesMensualesContables
.Include(r => r.Registros)
.FirstOrDefaultAsync(r => r.Id == reporteId);
if (reporte == null || reporte.Cerrado) return false;
try
{
// Remove existing records for this report (or handle updates carefully)
// For a simple bulk entry system, we might replace all or upsert by ID.
// Let's go with UPSERT based on ID.
var existingIds = reporte.Registros.Select(r => r.Id).ToList();
var incomingIds = registros.Where(r => r.Id > 0).Select(r => r.Id).ToList();
// Delete records that are no longer in the list
var toDelete = reporte.Registros.Where(r => !incomingIds.Contains(r.Id)).ToList();
_context.ContabilidadRegistros.RemoveRange(toDelete);
foreach (var registro in registros)
{
if (registro.Id > 0)
{
// Update
var existing = reporte.Registros.FirstOrDefault(r => r.Id == registro.Id);
if (existing != null)
{
existing.Tipo = registro.Tipo;
existing.Monto = registro.Monto;
existing.Fecha = registro.Fecha;
existing.Descripcion = registro.Descripcion;
_context.Entry(existing).State = EntityState.Modified;
}
}
else
{
// Add
registro.ReporteMensualId = reporteId;
registro.GrupoTrabajoId = reporte.GrupoTrabajoId;
_context.ContabilidadRegistros.Add(registro);
}
}
await _context.SaveChangesAsync();
return true;
}
catch
{
return false;
}
}
public async Task<decimal> CalcularSaldoActualAsync(long reporteId)
{
var reporte = await _context.ReportesMensualesContables
.Include(r => r.Registros)
.FirstOrDefaultAsync(r => r.Id == reporteId);
if (reporte == null) return 0;
decimal ingresos = reporte.Registros
.Where(r => r.Tipo == TipoMovimientoContable.Ingreso)
.Sum(r => r.Monto);
decimal egresos = reporte.Registros
.Where(r => r.Tipo == TipoMovimientoContable.Egreso)
.Sum(r => r.Monto);
return reporte.SaldoInicial + ingresos - egresos;
}
public async Task<bool> CerrarReporteAsync(long reporteId)
{
var reporte = await _context.ReportesMensualesContables.FindAsync(reporteId);
if (reporte == null || reporte.Cerrado) return false;
reporte.Cerrado = true;
_context.ReportesMensualesContables.Update(reporte);
await _context.SaveChangesAsync();
return true;
}
}