Diseño de un AuditoriaController con un patrón para añadir endpoints de historial para diferentes entidades. Implementación de la lógica de servicio y repositorio para obtener datos de las tablas _H para: Usuarios (gral_Usuarios_H) Pagos de Distribuidores (cue_PagosDistribuidor_H) Notas de Crédito/Débito (cue_CreditosDebitos_H) Entradas/Salidas de Distribuidores (dist_EntradasSalidas_H) Entradas/Salidas de Canillitas (dist_EntradasSalidasCanillas_H) Novedades de Canillitas (dist_dtNovedadesCanillas_H) Ajustes Manuales de Saldo (cue_SaldoAjustesHistorial) Tipos de Pago (cue_dtTipopago_H) Canillitas (Maestro) (dist_dtCanillas_H) Distribuidores (Maestro) (dist_dtDistribuidores_H) Empresas (Maestro) (dist_dtEmpresas_H) DTOs específicos para cada tipo de historial, incluyendo NombreUsuarioModifico. Frontend: Servicio auditoriaService.ts con métodos para llamar a cada endpoint de historial. Página AuditoriaGeneralPage.tsx con: Selector de "Tipo de Entidad a Auditar". Filtros comunes (Fechas, Usuario Modificador, Tipo de Modificación, ID Entidad). Un DataGrid que muestra las columnas dinámicamente según el tipo de entidad seleccionada. Lógica para cargar los datos correspondientes. DTOs de historial en TypeScript. Actualizaciones en AppRoutes.tsx y MainLayout.tsx para la nueva sección de Auditoría (restringida a SuperAdmin).
401 lines
23 KiB
C#
401 lines
23 KiB
C#
using GestionIntegral.Api.Data;
|
|
using GestionIntegral.Api.Data.Repositories.Contables;
|
|
using GestionIntegral.Api.Data.Repositories.Distribucion;
|
|
using GestionIntegral.Api.Dtos.Auditoria;
|
|
using GestionIntegral.Api.Dtos.Distribucion;
|
|
using GestionIntegral.Api.Models.Distribucion;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace GestionIntegral.Api.Services.Distribucion
|
|
{
|
|
public class EntradaSalidaDistService : IEntradaSalidaDistService
|
|
{
|
|
private readonly IEntradaSalidaDistRepository _esRepository;
|
|
private readonly IPublicacionRepository _publicacionRepository;
|
|
private readonly IDistribuidorRepository _distribuidorRepository;
|
|
private readonly IPrecioRepository _precioRepository;
|
|
private readonly IRecargoZonaRepository _recargoZonaRepository;
|
|
private readonly IPorcPagoRepository _porcPagoRepository;
|
|
private readonly ISaldoRepository _saldoRepository;
|
|
private readonly IEmpresaRepository _empresaRepository; // Para obtener IdEmpresa de la publicación
|
|
private readonly DbConnectionFactory _connectionFactory;
|
|
private readonly ILogger<EntradaSalidaDistService> _logger;
|
|
|
|
public EntradaSalidaDistService(
|
|
IEntradaSalidaDistRepository esRepository,
|
|
IPublicacionRepository publicacionRepository,
|
|
IDistribuidorRepository distribuidorRepository,
|
|
IPrecioRepository precioRepository,
|
|
IRecargoZonaRepository recargoZonaRepository,
|
|
IPorcPagoRepository porcPagoRepository,
|
|
ISaldoRepository saldoRepository,
|
|
IEmpresaRepository empresaRepository,
|
|
DbConnectionFactory connectionFactory,
|
|
ILogger<EntradaSalidaDistService> logger)
|
|
{
|
|
_esRepository = esRepository;
|
|
_publicacionRepository = publicacionRepository;
|
|
_distribuidorRepository = distribuidorRepository;
|
|
_precioRepository = precioRepository;
|
|
_recargoZonaRepository = recargoZonaRepository;
|
|
_porcPagoRepository = porcPagoRepository;
|
|
_saldoRepository = saldoRepository;
|
|
_empresaRepository = empresaRepository;
|
|
_connectionFactory = connectionFactory;
|
|
_logger = logger;
|
|
}
|
|
|
|
private async Task<EntradaSalidaDistDto> MapToDto(EntradaSalidaDist es)
|
|
{
|
|
if (es == null) return null!;
|
|
|
|
var publicacionData = await _publicacionRepository.GetByIdAsync(es.IdPublicacion);
|
|
var distribuidorData = await _distribuidorRepository.GetByIdAsync(es.IdDistribuidor);
|
|
|
|
// Obtener el valor bruto del movimiento
|
|
decimal valorBrutoMovimiento = await CalcularMontoMovimiento(
|
|
es.IdPublicacion, es.IdDistribuidor, es.Fecha, es.Cantidad,
|
|
es.TipoMovimiento, // Pasamos el tipo de movimiento original aquí
|
|
es.IdPrecio, es.IdRecargo, es.IdPorcentaje, distribuidorData.Distribuidor?.IdZona
|
|
);
|
|
|
|
decimal montoCalculadoParaDto = valorBrutoMovimiento;
|
|
|
|
return new EntradaSalidaDistDto
|
|
{
|
|
IdParte = es.IdParte,
|
|
IdPublicacion = es.IdPublicacion,
|
|
NombrePublicacion = publicacionData.Publicacion?.Nombre ?? "N/A",
|
|
IdEmpresaPublicacion = publicacionData.Publicacion?.IdEmpresa ?? 0,
|
|
NombreEmpresaPublicacion = publicacionData.NombreEmpresa ?? "N/A",
|
|
IdDistribuidor = es.IdDistribuidor,
|
|
NombreDistribuidor = distribuidorData.Distribuidor?.Nombre ?? "N/A",
|
|
Fecha = es.Fecha.ToString("yyyy-MM-dd"),
|
|
TipoMovimiento = es.TipoMovimiento,
|
|
Cantidad = es.Cantidad,
|
|
Remito = es.Remito,
|
|
Observacion = es.Observacion,
|
|
MontoCalculado = montoCalculadoParaDto // Representa el valor de los N ejemplares
|
|
};
|
|
}
|
|
|
|
private async Task<decimal> CalcularMontoMovimiento(int idPublicacion, int idDistribuidor, DateTime fecha, int cantidad, string tipoMovimiento,
|
|
int idPrecio, int idRecargo, int idPorcentaje, int? idZonaDistribuidor)
|
|
{
|
|
var precioConfig = await _precioRepository.GetByIdAsync(idPrecio);
|
|
// Es crucial que idPrecio sea válido y se haya determinado correctamente antes de llamar aquí.
|
|
// Si precioConfig es null, se lanzará una excepción abajo, lo cual está bien si es un estado inesperado.
|
|
if (precioConfig == null)
|
|
{
|
|
_logger.LogError("Configuración de precio ID {IdPrecio} no encontrada al calcular monto para Pub {IdPublicacion}, Dist {IdDistribuidor}, Fecha {Fecha}", idPrecio, idPublicacion, idDistribuidor, fecha);
|
|
// Dependiendo de la regla de negocio, podrías devolver 0 o lanzar una excepción.
|
|
// Si un precio es OBLIGATORIO para cualquier movimiento, lanzar excepción es más apropiado.
|
|
// Si puede haber movimientos sin precio (ej. cortesía que no se factura), entonces 0.
|
|
// En este contexto, un precio es fundamental para el cálculo.
|
|
throw new InvalidOperationException($"Configuración de precio ID {idPrecio} no encontrada. No se puede calcular el monto.");
|
|
}
|
|
|
|
decimal precioDia = 0;
|
|
DayOfWeek diaSemana = fecha.DayOfWeek;
|
|
switch (diaSemana)
|
|
{
|
|
case DayOfWeek.Monday: precioDia = precioConfig.Lunes ?? 0; break;
|
|
case DayOfWeek.Tuesday: precioDia = precioConfig.Martes ?? 0; break;
|
|
case DayOfWeek.Wednesday: precioDia = precioConfig.Miercoles ?? 0; break;
|
|
case DayOfWeek.Thursday: precioDia = precioConfig.Jueves ?? 0; break;
|
|
case DayOfWeek.Friday: precioDia = precioConfig.Viernes ?? 0; break;
|
|
case DayOfWeek.Saturday: precioDia = precioConfig.Sabado ?? 0; break;
|
|
case DayOfWeek.Sunday: precioDia = precioConfig.Domingo ?? 0; break;
|
|
}
|
|
|
|
decimal valorRecargo = 0;
|
|
if (idRecargo > 0 && idZonaDistribuidor.HasValue)
|
|
{
|
|
var recargoConfig = await _recargoZonaRepository.GetActiveByPublicacionZonaAndDateAsync(idPublicacion, idZonaDistribuidor.Value, fecha);
|
|
if (recargoConfig != null)
|
|
{
|
|
valorRecargo = recargoConfig.Valor;
|
|
}
|
|
}
|
|
|
|
decimal precioConRecargo = precioDia + valorRecargo;
|
|
decimal montoBase = precioConRecargo * cantidad;
|
|
|
|
if (idPorcentaje > 0)
|
|
{
|
|
var porcConfig = await _porcPagoRepository.GetByIdAsync(idPorcentaje);
|
|
if (porcConfig != null)
|
|
{
|
|
// El porcentaje de pago del distribuidor es lo que ÉL PAGA a la editorial.
|
|
// Entonces, el monto es (precio_tapa_con_recargo * cantidad) * (porcentaje_pago_dist / 100)
|
|
return (montoBase * porcConfig.Porcentaje) / 100;
|
|
}
|
|
}
|
|
// Si no hay porcentaje de pago específico, se asume que el distribuidor paga el 100% del monto base.
|
|
return montoBase;
|
|
}
|
|
|
|
|
|
public async Task<IEnumerable<EntradaSalidaDistDto>> ObtenerTodosAsync(DateTime? fechaDesde, DateTime? fechaHasta, int? idPublicacion, int? idDistribuidor, string? tipoMovimiento)
|
|
{
|
|
var movimientos = await _esRepository.GetAllAsync(fechaDesde, fechaHasta, idPublicacion, idDistribuidor, tipoMovimiento);
|
|
var dtos = new List<EntradaSalidaDistDto>();
|
|
foreach (var mov in movimientos)
|
|
{
|
|
dtos.Add(await MapToDto(mov));
|
|
}
|
|
return dtos;
|
|
}
|
|
|
|
public async Task<EntradaSalidaDistDto?> ObtenerPorIdAsync(int idParte)
|
|
{
|
|
var movimiento = await _esRepository.GetByIdAsync(idParte);
|
|
return movimiento == null ? null : await MapToDto(movimiento);
|
|
}
|
|
|
|
public async Task<(EntradaSalidaDistDto? Movimiento, string? Error)> CrearMovimientoAsync(CreateEntradaSalidaDistDto createDto, int idUsuario)
|
|
{
|
|
var publicacion = await _publicacionRepository.GetByIdSimpleAsync(createDto.IdPublicacion);
|
|
if (publicacion == null || publicacion.Habilitada != true) return (null, "Publicación no válida o no habilitada.");
|
|
|
|
var distribuidor = await _distribuidorRepository.GetByIdSimpleAsync(createDto.IdDistribuidor);
|
|
if (distribuidor == null) return (null, "Distribuidor no válido.");
|
|
|
|
if (await _esRepository.ExistsByRemitoAndTipoForPublicacionAsync(createDto.Remito, createDto.TipoMovimiento, createDto.IdPublicacion))
|
|
{
|
|
return (null, $"Ya existe un movimiento de '{createDto.TipoMovimiento}' con el remito N°{createDto.Remito} para esta publicación.");
|
|
}
|
|
|
|
// Determinar IDs de Precio, Recargo y Porcentaje activos en la fecha del movimiento
|
|
var precioActivo = await _precioRepository.GetActiveByPublicacionAndDateAsync(createDto.IdPublicacion, createDto.Fecha.Date);
|
|
if (precioActivo == null) return (null, $"No hay un precio definido para la publicación '{publicacion.Nombre}' en la fecha {createDto.Fecha:dd/MM/yyyy}.");
|
|
|
|
RecargoZona? recargoActivo = null;
|
|
if (distribuidor.IdZona.HasValue)
|
|
{
|
|
recargoActivo = await _recargoZonaRepository.GetActiveByPublicacionZonaAndDateAsync(createDto.IdPublicacion, distribuidor.IdZona.Value, createDto.Fecha.Date);
|
|
}
|
|
|
|
var porcPagoActivo = await _porcPagoRepository.GetActiveByPublicacionDistribuidorAndDateAsync(createDto.IdPublicacion, createDto.IdDistribuidor, createDto.Fecha.Date);
|
|
|
|
var nuevoES = new EntradaSalidaDist
|
|
{
|
|
IdPublicacion = createDto.IdPublicacion,
|
|
IdDistribuidor = createDto.IdDistribuidor,
|
|
Fecha = createDto.Fecha.Date,
|
|
TipoMovimiento = createDto.TipoMovimiento,
|
|
Cantidad = createDto.Cantidad,
|
|
Remito = createDto.Remito,
|
|
Observacion = createDto.Observacion,
|
|
IdPrecio = precioActivo.IdPrecio,
|
|
IdRecargo = recargoActivo?.IdRecargo ?? 0, // 0 si no aplica
|
|
IdPorcentaje = porcPagoActivo?.IdPorcentaje ?? 0 // 0 si no aplica
|
|
};
|
|
|
|
using var connection = _connectionFactory.CreateConnection();
|
|
if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open();
|
|
using var transaction = connection.BeginTransaction();
|
|
try
|
|
{
|
|
var esCreada = await _esRepository.CreateAsync(nuevoES, idUsuario, transaction);
|
|
if (esCreada == null) throw new DataException("Error al registrar el movimiento.");
|
|
|
|
// Afectar Saldo
|
|
decimal montoAfectacion = await CalcularMontoMovimiento(
|
|
esCreada.IdPublicacion, esCreada.IdDistribuidor, esCreada.Fecha, esCreada.Cantidad, esCreada.TipoMovimiento,
|
|
esCreada.IdPrecio, esCreada.IdRecargo, esCreada.IdPorcentaje, distribuidor.IdZona);
|
|
|
|
// Si es Salida, montoAfectacion es positivo (aumenta deuda). Si es Entrada, es 0 por CalcularMontoMovimiento,
|
|
// pero para el saldo, una Entrada (devolución) debería restar del saldo deudor.
|
|
// Por lo tanto, el monto real a restar del saldo si es Entrada sería el valor de esos ejemplares devueltos.
|
|
if (esCreada.TipoMovimiento == "Entrada")
|
|
{
|
|
// Recalcular como si fuera salida para obtener el valor a acreditar/restar del saldo
|
|
montoAfectacion = await CalcularMontoMovimiento(
|
|
esCreada.IdPublicacion, esCreada.IdDistribuidor, esCreada.Fecha, esCreada.Cantidad, "Salida", // Forzar tipo Salida para cálculo de valor
|
|
esCreada.IdPrecio, esCreada.IdRecargo, esCreada.IdPorcentaje, distribuidor.IdZona);
|
|
montoAfectacion *= -1; // Hacerlo negativo para restar del saldo
|
|
}
|
|
|
|
|
|
bool saldoActualizado = await _saldoRepository.ModificarSaldoAsync("Distribuidores", esCreada.IdDistribuidor, publicacion.IdEmpresa, montoAfectacion, transaction);
|
|
if (!saldoActualizado) throw new DataException("Error al actualizar el saldo del distribuidor.");
|
|
|
|
transaction.Commit();
|
|
_logger.LogInformation("Movimiento ID {Id} creado y saldo afectado por Usuario ID {UserId}.", esCreada.IdParte, idUsuario);
|
|
return (await MapToDto(esCreada), null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
try { transaction.Rollback(); } catch { }
|
|
_logger.LogError(ex, "Error CrearMovimientoAsync para Pub ID {IdPub}", createDto.IdPublicacion);
|
|
return (null, $"Error interno: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task<(bool Exito, string? Error)> ActualizarMovimientoAsync(int idParte, UpdateEntradaSalidaDistDto updateDto, int idUsuario)
|
|
{
|
|
// La actualización de un movimiento que afecta saldos es compleja.
|
|
// Si cambia la cantidad, el monto original y el nuevo deben calcularse,
|
|
// y la diferencia debe aplicarse al saldo.
|
|
// Por ahora, este DTO solo permite cambiar Cantidad y Observacion.
|
|
// Cambiar otros campos como Fecha, Publicacion, Distribuidor implicaría recalcular todo
|
|
// y posiblemente anular el movimiento original y crear uno nuevo.
|
|
|
|
using var connection = _connectionFactory.CreateConnection();
|
|
if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open();
|
|
using var transaction = connection.BeginTransaction();
|
|
try
|
|
{
|
|
var esExistente = await _esRepository.GetByIdAsync(idParte);
|
|
if (esExistente == null) return (false, "Movimiento no encontrado.");
|
|
|
|
var publicacion = await _publicacionRepository.GetByIdSimpleAsync(esExistente.IdPublicacion);
|
|
if (publicacion == null) return (false, "Publicación asociada no encontrada."); // Muy raro
|
|
var distribuidor = await _distribuidorRepository.GetByIdSimpleAsync(esExistente.IdDistribuidor);
|
|
if (distribuidor == null) return (false, "Distribuidor asociado no encontrado.");
|
|
|
|
|
|
// 1. Calcular monto del movimiento original (antes de la actualización)
|
|
decimal montoOriginal = await CalcularMontoMovimiento(
|
|
esExistente.IdPublicacion, esExistente.IdDistribuidor, esExistente.Fecha, esExistente.Cantidad, esExistente.TipoMovimiento,
|
|
esExistente.IdPrecio, esExistente.IdRecargo, esExistente.IdPorcentaje, distribuidor.IdZona);
|
|
if (esExistente.TipoMovimiento == "Entrada") montoOriginal *= -1; // Para revertir
|
|
|
|
// 2. Actualizar la entidad en la BD (esto también guarda en historial)
|
|
var esParaActualizar = new EntradaSalidaDist
|
|
{
|
|
IdParte = esExistente.IdParte,
|
|
IdPublicacion = esExistente.IdPublicacion, // No cambia
|
|
IdDistribuidor = esExistente.IdDistribuidor, // No cambia
|
|
Fecha = esExistente.Fecha, // No cambia
|
|
TipoMovimiento = esExistente.TipoMovimiento, // No cambia
|
|
Cantidad = updateDto.Cantidad, // Nuevo valor
|
|
Remito = esExistente.Remito, // No cambia
|
|
Observacion = updateDto.Observacion, // Nuevo valor
|
|
IdPrecio = esExistente.IdPrecio, // No cambia
|
|
IdRecargo = esExistente.IdRecargo, // No cambia
|
|
IdPorcentaje = esExistente.IdPorcentaje // No cambia
|
|
};
|
|
var actualizado = await _esRepository.UpdateAsync(esParaActualizar, idUsuario, transaction);
|
|
if (!actualizado) throw new DataException("Error al actualizar el movimiento.");
|
|
|
|
// 3. Calcular monto del movimiento nuevo (después de la actualización)
|
|
decimal montoNuevo = await CalcularMontoMovimiento(
|
|
esParaActualizar.IdPublicacion, esParaActualizar.IdDistribuidor, esParaActualizar.Fecha, esParaActualizar.Cantidad, esParaActualizar.TipoMovimiento,
|
|
esParaActualizar.IdPrecio, esParaActualizar.IdRecargo, esParaActualizar.IdPorcentaje, distribuidor.IdZona);
|
|
if (esParaActualizar.TipoMovimiento == "Entrada") montoNuevo *= -1;
|
|
|
|
|
|
// 4. Ajustar saldo con la diferencia
|
|
decimal diferenciaAjusteSaldo = montoNuevo - montoOriginal;
|
|
if (diferenciaAjusteSaldo != 0)
|
|
{
|
|
bool saldoActualizado = await _saldoRepository.ModificarSaldoAsync("Distribuidores", esExistente.IdDistribuidor, publicacion.IdEmpresa, diferenciaAjusteSaldo, transaction);
|
|
if (!saldoActualizado) throw new DataException("Error al ajustar el saldo del distribuidor tras la actualización.");
|
|
}
|
|
|
|
transaction.Commit();
|
|
_logger.LogInformation("Movimiento ID {Id} actualizado y saldo ajustado por Usuario ID {UserId}.", idParte, idUsuario);
|
|
return (true, null);
|
|
}
|
|
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch { } return (false, "Movimiento no encontrado."); }
|
|
catch (Exception ex)
|
|
{
|
|
try { transaction.Rollback(); } catch { }
|
|
_logger.LogError(ex, "Error ActualizarMovimientoAsync ID: {Id}", idParte);
|
|
return (false, $"Error interno: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task<(bool Exito, string? Error)> EliminarMovimientoAsync(int idParte, int idUsuario)
|
|
{
|
|
using var connection = _connectionFactory.CreateConnection();
|
|
if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open();
|
|
using var transaction = connection.BeginTransaction();
|
|
try
|
|
{
|
|
var esExistente = await _esRepository.GetByIdAsync(idParte);
|
|
if (esExistente == null) return (false, "Movimiento no encontrado.");
|
|
|
|
var publicacion = await _publicacionRepository.GetByIdSimpleAsync(esExistente.IdPublicacion);
|
|
if (publicacion == null) return (false, "Publicación asociada no encontrada.");
|
|
var distribuidor = await _distribuidorRepository.GetByIdSimpleAsync(esExistente.IdDistribuidor);
|
|
if (distribuidor == null) return (false, "Distribuidor asociado no encontrado.");
|
|
|
|
// 1. Calcular el monto del movimiento a eliminar para revertir el saldo
|
|
decimal montoReversion = await CalcularMontoMovimiento(
|
|
esExistente.IdPublicacion, esExistente.IdDistribuidor, esExistente.Fecha, esExistente.Cantidad, esExistente.TipoMovimiento,
|
|
esExistente.IdPrecio, esExistente.IdRecargo, esExistente.IdPorcentaje, distribuidor.IdZona);
|
|
|
|
// Si es Salida, el monto es positivo, al revertir restamos.
|
|
// Si es Entrada, el monto es 0 (por Calcular...), pero su efecto en saldo fue negativo, al revertir sumamos el valor.
|
|
if (esExistente.TipoMovimiento == "Salida")
|
|
{
|
|
montoReversion *= -1; // Para restar del saldo lo que se sumó
|
|
}
|
|
else if (esExistente.TipoMovimiento == "Entrada")
|
|
{
|
|
// Recalcular el valor como si fuera salida para saber cuánto se restó del saldo
|
|
montoReversion = await CalcularMontoMovimiento(
|
|
esExistente.IdPublicacion, esExistente.IdDistribuidor, esExistente.Fecha, esExistente.Cantidad, "Salida",
|
|
esExistente.IdPrecio, esExistente.IdRecargo, esExistente.IdPorcentaje, distribuidor.IdZona);
|
|
// No se multiplica por -1 aquí, porque el saldo ya lo tiene restado, al eliminar revertimos sumando.
|
|
}
|
|
|
|
|
|
// 2. Eliminar el registro (esto también guarda en historial)
|
|
var eliminado = await _esRepository.DeleteAsync(idParte, idUsuario, transaction);
|
|
if (!eliminado) throw new DataException("Error al eliminar el movimiento.");
|
|
|
|
// 3. Ajustar Saldo
|
|
bool saldoActualizado = await _saldoRepository.ModificarSaldoAsync("Distribuidores", esExistente.IdDistribuidor, publicacion.IdEmpresa, montoReversion, transaction);
|
|
if (!saldoActualizado) throw new DataException("Error al revertir el saldo del distribuidor tras la eliminación.");
|
|
|
|
transaction.Commit();
|
|
_logger.LogInformation("Movimiento ID {Id} eliminado y saldo revertido por Usuario ID {UserId}.", idParte, idUsuario);
|
|
return (true, null);
|
|
}
|
|
catch (KeyNotFoundException) { try { transaction.Rollback(); } catch { } return (false, "Movimiento no encontrado."); }
|
|
catch (Exception ex)
|
|
{
|
|
try { transaction.Rollback(); } catch { }
|
|
_logger.LogError(ex, "Error EliminarMovimientoAsync ID: {Id}", idParte);
|
|
return (false, $"Error interno: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<EntradaSalidaDistHistorialDto>> ObtenerHistorialAsync(
|
|
DateTime? fechaDesde, DateTime? fechaHasta,
|
|
int? idUsuarioModifico, string? tipoModificacion,
|
|
int? idParteAfectada)
|
|
{
|
|
var historialData = await _esRepository.GetHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idParteAfectada);
|
|
|
|
return historialData.Select(h => new EntradaSalidaDistHistorialDto
|
|
{
|
|
Id_Parte = h.Historial.Id_Parte,
|
|
Id_Publicacion = h.Historial.Id_Publicacion,
|
|
Id_Distribuidor = h.Historial.Id_Distribuidor,
|
|
Fecha = h.Historial.Fecha,
|
|
TipoMovimiento = h.Historial.TipoMovimiento,
|
|
Cantidad = h.Historial.Cantidad,
|
|
Remito = h.Historial.Remito,
|
|
Observacion = h.Historial.Observacion,
|
|
Id_Precio = h.Historial.Id_Precio,
|
|
Id_Recargo = h.Historial.Id_Recargo,
|
|
Id_Porcentaje = h.Historial.Id_Porcentaje,
|
|
Id_Usuario = h.Historial.Id_Usuario,
|
|
NombreUsuarioModifico = h.NombreUsuarioModifico,
|
|
FechaMod = h.Historial.FechaMod,
|
|
TipoMod = h.Historial.TipoMod
|
|
}).ToList();
|
|
}
|
|
}
|
|
} |