feat: Implementación de Secciones, Recargos, Porc. Pago Dist. y backend E/S Dist.
Backend API:
- Recargos por Zona (`dist_RecargoZona`):
- CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/recargos`.
- Lógica de negocio para vigencias (cierre/reapertura de períodos).
- Auditoría en `dist_RecargoZona_H`.
- Porcentajes de Pago Distribuidores (`dist_PorcPago`):
- CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/porcentajespago`.
- Lógica de negocio para vigencias.
- Auditoría en `dist_PorcPago_H`.
- Porcentajes/Montos Pago Canillitas (`dist_PorcMonPagoCanilla`):
- CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/porcentajesmoncanilla`.
- Lógica de negocio para vigencias.
- Auditoría en `dist_PorcMonPagoCanilla_H`.
- Secciones de Publicación (`dist_dtPubliSecciones`):
- CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/secciones`.
- Auditoría en `dist_dtPubliSecciones_H`.
- Entradas/Salidas Distribuidores (`dist_EntradasSalidas`):
- Implementado backend (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para determinar precios/recargos/porcentajes aplicables.
- Cálculo de monto y afectación de saldos de distribuidores en `cue_Saldos`.
- Auditoría en `dist_EntradasSalidas_H`.
- Correcciones de Mapeo Dapper:
- Aplicados alias explícitos en repositorios de RecargoZona, PorcPago, PorcMonCanilla, PubliSeccion,
Canilla, Distribuidor y Precio para asegurar mapeo correcto de IDs y columnas.
Frontend React:
- Recargos por Zona:
- `recargoZonaService.ts`.
- `RecargoZonaFormModal.tsx` para crear/editar períodos de recargos.
- `GestionarRecargosPublicacionPage.tsx` para listar y gestionar recargos por publicación.
- Porcentajes de Pago Distribuidores:
- `porcPagoService.ts`.
- `PorcPagoFormModal.tsx`.
- `GestionarPorcentajesPagoPage.tsx`.
- Porcentajes/Montos Pago Canillitas:
- `porcMonCanillaService.ts`.
- `PorcMonCanillaFormModal.tsx`.
- `GestionarPorcMonCanillaPage.tsx`.
- Secciones de Publicación:
- `publiSeccionService.ts`.
- `PubliSeccionFormModal.tsx`.
- `GestionarSeccionesPublicacionPage.tsx`.
- Navegación:
- Actualizadas rutas y menús para acceder a la gestión de recargos, porcentajes (dist. y canillita) y secciones desde la vista de una publicación.
- Layout:
- Uso consistente de `Box` con Flexbox en lugar de `Grid` en nuevos modales y páginas para evitar errores de tipo.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using Dapper;
|
||||
using GestionIntegral.Api.Data.Repositories;
|
||||
using GestionIntegral.Api.Models.Distribucion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System; // Para Exception
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
@@ -24,10 +24,14 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
public async Task<IEnumerable<(Canilla Canilla, string NombreZona, string NombreEmpresa)>> GetAllAsync(string? nomApeFilter, int? legajoFilter, bool? soloActivos)
|
||||
{
|
||||
var sqlBuilder = new StringBuilder(@"
|
||||
SELECT c.*, z.Nombre AS NombreZona, ISNULL(e.Nombre, 'N/A (Accionista)') AS NombreEmpresa
|
||||
SELECT
|
||||
c.Id_Canilla AS IdCanilla, c.Legajo, c.NomApe, c.Parada, c.Id_Zona AS IdZona,
|
||||
c.Accionista, c.Obs, c.Empresa, c.Baja, c.FechaBaja,
|
||||
z.Nombre AS NombreZona,
|
||||
ISNULL(e.Nombre, 'N/A (Accionista)') AS NombreEmpresa
|
||||
FROM dbo.dist_dtCanillas c
|
||||
INNER JOIN dbo.dist_dtZonas z ON c.Id_Zona = z.Id_Zona
|
||||
LEFT JOIN dbo.dist_dtEmpresas e ON c.Empresa = e.Id_Empresa -- Empresa 0 no tendrá join
|
||||
LEFT JOIN dbo.dist_dtEmpresas e ON c.Empresa = e.Id_Empresa
|
||||
WHERE 1=1");
|
||||
var parameters = new DynamicParameters();
|
||||
|
||||
@@ -37,13 +41,13 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(nomApeFilter))
|
||||
{
|
||||
sqlBuilder.Append(" AND c.NomApe LIKE @NomApe");
|
||||
parameters.Add("NomApe", $"%{nomApeFilter}%");
|
||||
sqlBuilder.Append(" AND c.NomApe LIKE @NomApeParam");
|
||||
parameters.Add("NomApeParam", $"%{nomApeFilter}%");
|
||||
}
|
||||
if (legajoFilter.HasValue)
|
||||
{
|
||||
sqlBuilder.Append(" AND c.Legajo = @Legajo");
|
||||
parameters.Add("Legajo", legajoFilter.Value);
|
||||
sqlBuilder.Append(" AND c.Legajo = @LegajoParam");
|
||||
parameters.Add("LegajoParam", legajoFilter.Value);
|
||||
}
|
||||
sqlBuilder.Append(" ORDER BY c.NomApe;");
|
||||
|
||||
@@ -59,7 +63,7 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener todos los Canillas.");
|
||||
_logger.LogError(ex, "Error al obtener todos los Canillas. Filtros: NomApe='{NomApeFilter}', Legajo='{LegajoFilter}', SoloActivos='{SoloActivos}'", nomApeFilter, legajoFilter, soloActivos);
|
||||
return Enumerable.Empty<(Canilla, string, string)>();
|
||||
}
|
||||
}
|
||||
@@ -67,18 +71,22 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
public async Task<(Canilla? Canilla, string? NombreZona, string? NombreEmpresa)> GetByIdAsync(int id)
|
||||
{
|
||||
const string sql = @"
|
||||
SELECT c.*, z.Nombre AS NombreZona, ISNULL(e.Nombre, 'N/A (Accionista)') AS NombreEmpresa
|
||||
SELECT
|
||||
c.Id_Canilla AS IdCanilla, c.Legajo, c.NomApe, c.Parada, c.Id_Zona AS IdZona,
|
||||
c.Accionista, c.Obs, c.Empresa, c.Baja, c.FechaBaja,
|
||||
z.Nombre AS NombreZona,
|
||||
ISNULL(e.Nombre, 'N/A (Accionista)') AS NombreEmpresa
|
||||
FROM dbo.dist_dtCanillas c
|
||||
INNER JOIN dbo.dist_dtZonas z ON c.Id_Zona = z.Id_Zona
|
||||
LEFT JOIN dbo.dist_dtEmpresas e ON c.Empresa = e.Id_Empresa
|
||||
WHERE c.Id_Canilla = @Id";
|
||||
WHERE c.Id_Canilla = @IdParam";
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
var result = await connection.QueryAsync<Canilla, string, string, (Canilla, string, string)>(
|
||||
var result = await connection.QueryAsync<Canilla, string, string, (Canilla?, string?, string?)>(
|
||||
sql,
|
||||
(canilla, nombreZona, nombreEmpresa) => (canilla, nombreZona, nombreEmpresa),
|
||||
new { Id = id },
|
||||
new { IdParam = id },
|
||||
splitOn: "NombreZona,NombreEmpresa"
|
||||
);
|
||||
return result.SingleOrDefault();
|
||||
@@ -89,25 +97,37 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
return (null, null, null);
|
||||
}
|
||||
}
|
||||
public async Task<Canilla?> GetByIdSimpleAsync(int id) // Para uso interno del servicio
|
||||
public async Task<Canilla?> GetByIdSimpleAsync(int id)
|
||||
{
|
||||
const string sql = "SELECT * FROM dbo.dist_dtCanillas WHERE Id_Canilla = @Id";
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<Canilla>(sql, new { Id = id });
|
||||
const string sql = @"
|
||||
SELECT
|
||||
Id_Canilla AS IdCanilla, Legajo, NomApe, Parada, Id_Zona AS IdZona,
|
||||
Accionista, Obs, Empresa, Baja, FechaBaja
|
||||
FROM dbo.dist_dtCanillas
|
||||
WHERE Id_Canilla = @IdParam";
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<Canilla>(sql, new { IdParam = id });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener Canilla (simple) por ID: {IdCanilla}", id);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> ExistsByLegajoAsync(int legajo, int? excludeIdCanilla = null)
|
||||
{
|
||||
if (legajo == 0) return false; // Legajo 0 es como nulo, no debería validarse como único
|
||||
var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.dist_dtCanillas WHERE Legajo = @Legajo AND Legajo != 0"); // Excluir legajo 0 de la unicidad
|
||||
if (legajo == 0) return false;
|
||||
var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.dist_dtCanillas WHERE Legajo = @LegajoParam AND Legajo != 0");
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("Legajo", legajo);
|
||||
parameters.Add("LegajoParam", legajo);
|
||||
|
||||
if (excludeIdCanilla.HasValue)
|
||||
{
|
||||
sqlBuilder.Append(" AND Id_Canilla != @ExcludeIdCanilla");
|
||||
parameters.Add("ExcludeIdCanilla", excludeIdCanilla.Value);
|
||||
sqlBuilder.Append(" AND Id_Canilla != @ExcludeIdCanillaParam");
|
||||
parameters.Add("ExcludeIdCanillaParam", excludeIdCanilla.Value);
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -125,23 +145,24 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
{
|
||||
const string sqlInsert = @"
|
||||
INSERT INTO dbo.dist_dtCanillas (Legajo, NomApe, Parada, Id_Zona, Accionista, Obs, Empresa, Baja, FechaBaja)
|
||||
OUTPUT INSERTED.*
|
||||
OUTPUT INSERTED.Id_Canilla AS IdCanilla, INSERTED.Legajo, INSERTED.NomApe, INSERTED.Parada, INSERTED.Id_Zona AS IdZona,
|
||||
INSERTED.Accionista, INSERTED.Obs, INSERTED.Empresa, INSERTED.Baja, INSERTED.FechaBaja
|
||||
VALUES (@Legajo, @NomApe, @Parada, @IdZona, @Accionista, @Obs, @Empresa, @Baja, @FechaBaja);";
|
||||
const string sqlInsertHistorico = @"
|
||||
INSERT INTO dbo.dist_dtCanillas_H
|
||||
(Id_Canilla, Legajo, NomApe, Parada, Id_Zona, Accionista, Obs, Empresa, Baja, FechaBaja, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdCanilla, @Legajo, @NomApe, @Parada, @IdZona, @Accionista, @Obs, @Empresa, @Baja, @FechaBaja, @Id_Usuario, @FechaMod, @TipoMod);";
|
||||
|
||||
var connection = transaction.Connection!;
|
||||
var insertedCanilla = await connection.QuerySingleAsync<Canilla>(sqlInsert, nuevoCanilla, transaction);
|
||||
|
||||
if (insertedCanilla == null) throw new DataException("No se pudo crear el canilla.");
|
||||
if (insertedCanilla == null || insertedCanilla.IdCanilla == 0) throw new DataException("No se pudo crear el canillita o obtener su ID.");
|
||||
|
||||
const string sqlInsertHistorico = @"
|
||||
INSERT INTO dbo.dist_dtCanillas_H
|
||||
(Id_Canilla, Legajo, NomApe, Parada, Id_Zona, Accionista, Obs, Empresa, Baja, FechaBaja, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdCanillaParam, @LegajoParam, @NomApeParam, @ParadaParam, @IdZonaParam, @AccionistaParam, @ObsParam, @EmpresaParam, @BajaParam, @FechaBajaParam, @Id_UsuarioParam, @FechaModParam, @TipoModParam);";
|
||||
|
||||
await connection.ExecuteAsync(sqlInsertHistorico, new
|
||||
{
|
||||
insertedCanilla.IdCanilla, insertedCanilla.Legajo, insertedCanilla.NomApe, insertedCanilla.Parada, insertedCanilla.IdZona,
|
||||
insertedCanilla.Accionista, insertedCanilla.Obs, insertedCanilla.Empresa, insertedCanilla.Baja, insertedCanilla.FechaBaja,
|
||||
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Creado"
|
||||
IdCanillaParam = insertedCanilla.IdCanilla, LegajoParam = insertedCanilla.Legajo, NomApeParam = insertedCanilla.NomApe, ParadaParam = insertedCanilla.Parada, IdZonaParam = insertedCanilla.IdZona,
|
||||
AccionistaParam = insertedCanilla.Accionista, ObsParam = insertedCanilla.Obs, EmpresaParam = insertedCanilla.Empresa, BajaParam = insertedCanilla.Baja, FechaBajaParam = insertedCanilla.FechaBaja,
|
||||
Id_UsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModParam = "Creado"
|
||||
}, transaction);
|
||||
return insertedCanilla;
|
||||
}
|
||||
@@ -150,27 +171,29 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
{
|
||||
var connection = transaction.Connection!;
|
||||
var canillaActual = await connection.QuerySingleOrDefaultAsync<Canilla>(
|
||||
"SELECT * FROM dbo.dist_dtCanillas WHERE Id_Canilla = @IdCanilla", new { canillaAActualizar.IdCanilla }, transaction);
|
||||
@"SELECT Id_Canilla AS IdCanilla, Legajo, NomApe, Parada, Id_Zona AS IdZona,
|
||||
Accionista, Obs, Empresa, Baja, FechaBaja
|
||||
FROM dbo.dist_dtCanillas WHERE Id_Canilla = @IdCanillaParam",
|
||||
new { IdCanillaParam = canillaAActualizar.IdCanilla }, transaction);
|
||||
if (canillaActual == null) throw new KeyNotFoundException("Canilla no encontrado para actualizar.");
|
||||
|
||||
const string sqlUpdate = @"
|
||||
UPDATE dbo.dist_dtCanillas SET
|
||||
Legajo = @Legajo, NomApe = @NomApe, Parada = @Parada, Id_Zona = @IdZona,
|
||||
Accionista = @Accionista, Obs = @Obs, Empresa = @Empresa
|
||||
-- Baja y FechaBaja se manejan por ToggleBajaAsync
|
||||
WHERE Id_Canilla = @IdCanilla;";
|
||||
const string sqlInsertHistorico = @"
|
||||
INSERT INTO dbo.dist_dtCanillas_H
|
||||
(Id_Canilla, Legajo, NomApe, Parada, Id_Zona, Accionista, Obs, Empresa, Baja, FechaBaja, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdCanilla, @LegajoActual, @NomApeActual, @ParadaActual, @IdZonaActual, @AccionistaActual, @ObsActual, @EmpresaActual, @BajaActual, @FechaBajaActual, @Id_Usuario, @FechaMod, @TipoMod);";
|
||||
VALUES (@IdCanillaParam, @LegajoParam, @NomApeParam, @ParadaParam, @IdZonaParam, @AccionistaParam, @ObsParam, @EmpresaParam, @BajaParam, @FechaBajaParam, @Id_UsuarioParam, @FechaModParam, @TipoModParam);";
|
||||
|
||||
await connection.ExecuteAsync(sqlInsertHistorico, new
|
||||
{
|
||||
IdCanilla = canillaActual.IdCanilla,
|
||||
LegajoActual = canillaActual.Legajo, NomApeActual = canillaActual.NomApe, ParadaActual = canillaActual.Parada, IdZonaActual = canillaActual.IdZona,
|
||||
AccionistaActual = canillaActual.Accionista, ObsActual = canillaActual.Obs, EmpresaActual = canillaActual.Empresa,
|
||||
BajaActual = canillaActual.Baja, FechaBajaActual = canillaActual.FechaBaja, // Registrar estado actual de baja
|
||||
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Actualizado"
|
||||
IdCanillaParam = canillaActual.IdCanilla,
|
||||
LegajoParam = canillaActual.Legajo, NomApeParam = canillaActual.NomApe, ParadaParam = canillaActual.Parada, IdZonaParam = canillaActual.IdZona,
|
||||
AccionistaParam = canillaActual.Accionista, ObsParam = canillaActual.Obs, EmpresaParam = canillaActual.Empresa,
|
||||
BajaParam = canillaActual.Baja, FechaBajaParam = canillaActual.FechaBaja,
|
||||
Id_UsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModParam = "Actualizado"
|
||||
}, transaction);
|
||||
|
||||
var rowsAffected = await connection.ExecuteAsync(sqlUpdate, canillaAActualizar, transaction);
|
||||
@@ -181,24 +204,27 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
{
|
||||
var connection = transaction.Connection!;
|
||||
var canillaActual = await connection.QuerySingleOrDefaultAsync<Canilla>(
|
||||
"SELECT * FROM dbo.dist_dtCanillas WHERE Id_Canilla = @IdCanilla", new { IdCanilla = id }, transaction);
|
||||
@"SELECT Id_Canilla AS IdCanilla, Legajo, NomApe, Parada, Id_Zona AS IdZona,
|
||||
Accionista, Obs, Empresa, Baja, FechaBaja
|
||||
FROM dbo.dist_dtCanillas WHERE Id_Canilla = @IdCanillaParam",
|
||||
new { IdCanillaParam = id }, transaction);
|
||||
if (canillaActual == null) throw new KeyNotFoundException("Canilla no encontrado para dar de baja/alta.");
|
||||
|
||||
const string sqlUpdate = "UPDATE dbo.dist_dtCanillas SET Baja = @Baja, FechaBaja = @FechaBaja WHERE Id_Canilla = @IdCanilla;";
|
||||
const string sqlUpdate = "UPDATE dbo.dist_dtCanillas SET Baja = @BajaParam, FechaBaja = @FechaBajaParam WHERE Id_Canilla = @IdCanillaParam;";
|
||||
const string sqlInsertHistorico = @"
|
||||
INSERT INTO dbo.dist_dtCanillas_H
|
||||
(Id_Canilla, Legajo, NomApe, Parada, Id_Zona, Accionista, Obs, Empresa, Baja, FechaBaja, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdCanilla, @Legajo, @NomApe, @Parada, @IdZona, @Accionista, @Obs, @Empresa, @BajaNueva, @FechaBajaNueva, @Id_Usuario, @FechaMod, @TipoModHist);";
|
||||
VALUES (@IdCanillaParam, @LegajoParam, @NomApeParam, @ParadaParam, @IdZonaParam, @AccionistaParam, @ObsParam, @EmpresaParam, @BajaNuevaParam, @FechaBajaNuevaParam, @Id_UsuarioParam, @FechaModParam, @TipoModHistParam);";
|
||||
|
||||
await connection.ExecuteAsync(sqlInsertHistorico, new
|
||||
{
|
||||
canillaActual.IdCanilla, canillaActual.Legajo, canillaActual.NomApe, canillaActual.Parada, canillaActual.IdZona,
|
||||
canillaActual.Accionista, canillaActual.Obs, canillaActual.Empresa,
|
||||
BajaNueva = darDeBaja, FechaBajaNueva = (darDeBaja ? fechaBaja : null), // FechaBaja solo si se da de baja
|
||||
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoModHist = (darDeBaja ? "Baja" : "Alta")
|
||||
IdCanillaParam = canillaActual.IdCanilla, LegajoParam = canillaActual.Legajo, NomApeParam = canillaActual.NomApe, ParadaParam = canillaActual.Parada, IdZonaParam = canillaActual.IdZona,
|
||||
AccionistaParam = canillaActual.Accionista, ObsParam = canillaActual.Obs, EmpresaParam = canillaActual.Empresa,
|
||||
BajaNuevaParam = darDeBaja, FechaBajaNuevaParam = (darDeBaja ? fechaBaja : null),
|
||||
Id_UsuarioParam = idUsuario, FechaModParam = DateTime.Now, TipoModHistParam = (darDeBaja ? "Baja" : "Alta")
|
||||
}, transaction);
|
||||
|
||||
var rowsAffected = await connection.ExecuteAsync(sqlUpdate, new { Baja = darDeBaja, FechaBaja = (darDeBaja ? fechaBaja : null), IdCanilla = id }, transaction);
|
||||
var rowsAffected = await connection.ExecuteAsync(sqlUpdate, new { BajaParam = darDeBaja, FechaBajaParam = (darDeBaja ? fechaBaja : null), IdCanillaParam = id }, transaction);
|
||||
return rowsAffected == 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user