Ya perdí el hilo de los cambios pero ahi van.

This commit is contained in:
2025-05-23 15:47:39 -03:00
parent e7e185a9cb
commit 3c1fe15b1f
141 changed files with 9764 additions and 190 deletions

View File

@@ -57,9 +57,29 @@ namespace GestionIntegral.Api.Services.Distribucion
var publicacionData = await _publicacionRepository.GetByIdAsync(es.IdPublicacion);
var distribuidorData = await _distribuidorRepository.GetByIdAsync(es.IdDistribuidor);
decimal montoCalculado = await CalcularMontoMovimiento(es.IdPublicacion, es.IdDistribuidor, es.Fecha, es.Cantidad, es.TipoMovimiento,
es.IdPrecio, es.IdRecargo, es.IdPorcentaje, distribuidorData.Distribuidor?.IdZona);
// 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
);
// Ajustar para el DTO: si es "Entrada", el monto calculado es un crédito (negativo o positivo según convención)
// Para consistencia con el ajuste de saldo, si es Entrada, el MontoCalculado para el DTO puede ser el valor
// que se le "acredita" al distribuidor (o sea, el valor de la mercadería devuelta).
// La lógica de +/- para el saldo ya está en Crear/Actualizar/Eliminar.
// Aquí solo mostramos el valor del movimiento. Si es entrada, es el valor de lo devuelto.
// Si es salida, es el valor de lo que se le factura.
// El método CalcularMonto ya devuelve el monto que el distribuidor DEBE pagar por una SALIDA.
// Para una ENTRADA (devolución), el valor de esa mercadería es el mismo, pero opera en sentido contrario al saldo.
decimal montoCalculadoParaDto = valorBrutoMovimiento;
// Si queremos que el DTO muestre las entradas como un valor que "reduce la deuda",
// podría ser positivo. Si queremos que refleje el impacto directo en la factura (salidas suman, entradas restan),
// podríamos hacerlo negativo.
// Por ahora, dejaremos que CalcularMontoMovimiento devuelva el valor de una "Salida",
// y si es "Entrada", este mismo valor es el que se acredita.
// La columna `MontoCalculado` en el DTO representará el valor de la transacción.
return new EntradaSalidaDistDto
{
@@ -75,17 +95,29 @@ namespace GestionIntegral.Api.Services.Distribucion
Cantidad = es.Cantidad,
Remito = es.Remito,
Observacion = es.Observacion,
MontoCalculado = montoCalculado
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)
{
if (tipoMovimiento == "Entrada") return 0; // Las entradas (devoluciones) no generan "debe" inmediato, ajustan el saldo.
// YA NO SE DEVUELVE 0 PARA ENTRADA AQUÍ
// if (tipoMovimiento == "Entrada") return 0;
var precioConfig = await _precioRepository.GetByIdAsync(idPrecio);
if (precioConfig == null) throw new InvalidOperationException("Configuración de precio no encontrada para el movimiento.");
// 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;
@@ -101,9 +133,8 @@ namespace GestionIntegral.Api.Services.Distribucion
}
decimal valorRecargo = 0;
if (idRecargo > 0 && idZonaDistribuidor.HasValue) // El recargo se aplica por la zona del distribuidor
if (idRecargo > 0 && idZonaDistribuidor.HasValue)
{
// Necesitamos encontrar el recargo activo para la publicación, la zona del distribuidor y la fecha
var recargoConfig = await _recargoZonaRepository.GetActiveByPublicacionZonaAndDateAsync(idPublicacion, idZonaDistribuidor.Value, fecha);
if (recargoConfig != null)
{
@@ -119,10 +150,13 @@ namespace GestionIntegral.Api.Services.Distribucion
var porcConfig = await _porcPagoRepository.GetByIdAsync(idPorcentaje);
if (porcConfig != null)
{
return (montoBase / 100) * porcConfig.Porcentaje;
// 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;
}
}
return montoBase; // Si no hay porcentaje, se factura el 100% del precio con recargo
// Si no hay porcentaje de pago específico, se asume que el distribuidor paga el 100% del monto base.
return montoBase;
}