feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
using GestionIntegral.Api.Data ; // Para DbConnectionFactory
using GestionIntegral.Api.Data.Repositories.Usuarios ;
2025-06-12 19:36:21 -03:00
using GestionIntegral.Api.Dtos.Auditoria ;
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
using GestionIntegral.Api.Dtos.Usuarios ;
using GestionIntegral.Api.Models.Usuarios ;
using Microsoft.Extensions.Logging ;
using System.Collections.Generic ;
using System.Data ; // Para IsolationLevel
using System.Linq ;
using System.Threading.Tasks ;
namespace GestionIntegral.Api.Services.Usuarios
{
public class PerfilService : IPerfilService
{
private readonly IPerfilRepository _perfilRepository ;
private readonly DbConnectionFactory _connectionFactory ; // Necesario para transacciones
private readonly ILogger < PerfilService > _logger ;
private readonly IPermisoRepository _permisoRepository ;
public PerfilService ( IPerfilRepository perfilRepository , IPermisoRepository permisoRepository , DbConnectionFactory connectionFactory , ILogger < PerfilService > logger )
{
_perfilRepository = perfilRepository ;
_permisoRepository = permisoRepository ;
_connectionFactory = connectionFactory ; // Inyectar DbConnectionFactory
_logger = logger ;
}
private PerfilDto MapToDto ( Perfil perfil ) = > new PerfilDto
{
Id = perfil . Id ,
NombrePerfil = perfil . NombrePerfil ,
Descripcion = perfil . Descripcion
} ;
public async Task < IEnumerable < PerfilDto > > ObtenerTodosAsync ( string? nombreFilter )
{
var perfiles = await _perfilRepository . GetAllAsync ( nombreFilter ) ;
return perfiles . Select ( MapToDto ) ;
}
public async Task < PerfilDto ? > ObtenerPorIdAsync ( int id )
{
var perfil = await _perfilRepository . GetByIdAsync ( id ) ;
return perfil = = null ? null : MapToDto ( perfil ) ;
}
public async Task < ( PerfilDto ? Perfil , string? Error ) > CrearAsync ( CreatePerfilDto createDto , int idUsuario )
{
if ( await _perfilRepository . ExistsByNameAsync ( createDto . NombrePerfil ) )
{
return ( null , "El nombre del perfil ya existe." ) ;
}
var nuevoPerfil = new Perfil { NombrePerfil = createDto . NombrePerfil , Descripcion = createDto . Descripcion } ;
using var connection = _connectionFactory . CreateConnection ( ) ;
if ( connection is System . Data . Common . DbConnection dbConn ) await dbConn . OpenAsync ( ) ; else connection . Open ( ) ;
using var transaction = connection . BeginTransaction ( IsolationLevel . ReadCommitted ) ;
try
{
var perfilCreado = await _perfilRepository . CreateAsync ( nuevoPerfil , idUsuario , transaction ) ;
if ( perfilCreado = = null ) throw new DataException ( "La creación en el repositorio devolvió null." ) ;
transaction . Commit ( ) ;
_logger . LogInformation ( "Perfil ID {IdPerfil} creado por Usuario ID {IdUsuario}." , perfilCreado . Id , idUsuario ) ;
return ( MapToDto ( perfilCreado ) , null ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback CrearAsync Perfil." ) ; }
_logger . LogError ( ex , "Error CrearAsync Perfil. Nombre: {NombrePerfil}" , createDto . NombrePerfil ) ;
return ( null , $"Error interno al crear el perfil: {ex.Message}" ) ;
}
}
public async Task < ( bool Exito , string? Error ) > ActualizarAsync ( int id , UpdatePerfilDto updateDto , int idUsuario )
{
// Verificar existencia ANTES de iniciar la transacción para evitar trabajo innecesario
var perfilExistente = await _perfilRepository . GetByIdAsync ( id ) ;
if ( perfilExistente = = null ) return ( false , "Perfil no encontrado." ) ;
if ( await _perfilRepository . ExistsByNameAsync ( updateDto . NombrePerfil , id ) )
{
return ( false , "El nombre del perfil ya existe para otro registro." ) ;
}
var perfilAActualizar = new Perfil { Id = id , NombrePerfil = updateDto . NombrePerfil , Descripcion = updateDto . Descripcion } ;
using var connection = _connectionFactory . CreateConnection ( ) ;
if ( connection is System . Data . Common . DbConnection dbConn ) await dbConn . OpenAsync ( ) ; else connection . Open ( ) ;
using var transaction = connection . BeginTransaction ( IsolationLevel . ReadCommitted ) ;
try
{
var actualizado = await _perfilRepository . UpdateAsync ( perfilAActualizar , idUsuario , transaction ) ;
if ( ! actualizado )
{
// El repositorio ahora lanza KeyNotFoundException si no lo encuentra DENTRO de la tx.
// Si devuelve false sin excepción, podría ser otro error.
throw new DataException ( "La operación de actualización no afectó ninguna fila o falló." ) ;
}
transaction . Commit ( ) ;
_logger . LogInformation ( "Perfil ID {IdPerfil} actualizado por Usuario ID {IdUsuario}." , id , idUsuario ) ;
return ( true , null ) ;
}
catch ( KeyNotFoundException knfex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback ActualizarAsync Perfil (KeyNotFound)." ) ; }
_logger . LogWarning ( knfex , "Intento de actualizar Perfil ID: {Id} no encontrado dentro de la transacción." , id ) ;
return ( false , "Perfil no encontrado." ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback ActualizarAsync Perfil." ) ; }
_logger . LogError ( ex , "Error ActualizarAsync Perfil ID: {Id}" , id ) ;
return ( false , $"Error interno al actualizar el perfil: {ex.Message}" ) ;
}
}
public async Task < ( bool Exito , string? Error ) > EliminarAsync ( int id , int idUsuario )
{
// Verificar existencia y si está en uso ANTES de la transacción
var perfilExistente = await _perfilRepository . GetByIdAsync ( id ) ;
if ( perfilExistente = = null ) return ( false , "Perfil no encontrado." ) ;
if ( await _perfilRepository . IsInUseAsync ( id ) )
{
return ( false , "No se puede eliminar. El perfil está asignado a usuarios o permisos." ) ;
}
using var connection = _connectionFactory . CreateConnection ( ) ;
if ( connection is System . Data . Common . DbConnection dbConn ) await dbConn . OpenAsync ( ) ; else connection . Open ( ) ;
using var transaction = connection . BeginTransaction ( IsolationLevel . ReadCommitted ) ;
try
{
var eliminado = await _perfilRepository . DeleteAsync ( id , idUsuario , transaction ) ;
if ( ! eliminado )
{
throw new DataException ( "La operación de eliminación no afectó ninguna fila o falló." ) ;
}
transaction . Commit ( ) ;
_logger . LogInformation ( "Perfil ID {IdPerfil} eliminado por Usuario ID {IdUsuario}." , id , idUsuario ) ;
return ( true , null ) ;
}
catch ( KeyNotFoundException knfex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback EliminarAsync Perfil (KeyNotFound)." ) ; }
_logger . LogWarning ( knfex , "Intento de eliminar Perfil ID: {Id} no encontrado dentro de la transacción." , id ) ;
return ( false , "Perfil no encontrado." ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback EliminarAsync Perfil." ) ; }
_logger . LogError ( ex , "Error EliminarAsync Perfil ID: {Id}" , id ) ;
return ( false , $"Error interno al eliminar el perfil: {ex.Message}" ) ;
}
}
public async Task < IEnumerable < PermisoAsignadoDto > > ObtenerPermisosAsignadosAsync ( int idPerfil )
{
// 1. Obtener todos los permisos definidos en el sistema
var todosLosPermisos = await _permisoRepository . GetAllAsync ( null , null ) ; // Sin filtros
// 2. Obtener los IDs de los permisos actualmente asignados a este perfil
var idsPermisosAsignados = ( await _perfilRepository . GetPermisoIdsByPerfilIdAsync ( idPerfil ) ) . ToHashSet ( ) ;
// 3. Mapear a DTO, marcando 'Asignado'
var resultado = todosLosPermisos . Select ( p = > new PermisoAsignadoDto
{
Id = p . Id ,
Modulo = p . Modulo ,
DescPermiso = p . DescPermiso ,
CodAcc = p . CodAcc ,
Asignado = idsPermisosAsignados . Contains ( p . Id )
} ) . OrderBy ( p = > p . Modulo ) . ThenBy ( p = > p . DescPermiso ) ; // Ordenar para la UI
return resultado ;
}
public async Task < ( bool Exito , string? Error ) > ActualizarPermisosAsignadosAsync (
2025-06-12 19:36:21 -03:00
int idPerfil ,
ActualizarPermisosPerfilRequestDto request ,
int idUsuarioModificador )
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
{
// Validación: Verificar que el perfil exista
var perfil = await _perfilRepository . GetByIdAsync ( idPerfil ) ;
if ( perfil = = null )
{
return ( false , "Perfil no encontrado." ) ;
}
2025-06-12 19:36:21 -03:00
// --- INICIO DE LA LÓGICA DE AUDITORÍA ---
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
using var connection = _connectionFactory . CreateConnection ( ) ;
if ( connection is System . Data . Common . DbConnection dbConn ) await dbConn . OpenAsync ( ) ; else connection . Open ( ) ;
using var transaction = connection . BeginTransaction ( IsolationLevel . ReadCommitted ) ;
try
{
2025-06-12 19:36:21 -03:00
// 1. Obtener los IDs de permisos actuales DENTRO de la transacción para evitar race conditions
var idsActuales = ( await _perfilRepository . GetPermisoIdsByPerfilIdAsync ( idPerfil ) ) . ToHashSet ( ) ;
var idsNuevos = ( request . PermisosIds ? ? new List < int > ( ) ) . ToHashSet ( ) ;
// 2. Calcular las diferencias
var permisosAñadidos = idsNuevos . Where ( id = > ! idsActuales . Contains ( id ) ) . ToList ( ) ;
var permisosQuitados = idsActuales . Where ( id = > ! idsNuevos . Contains ( id ) ) . ToList ( ) ;
// 3. Registrar en el historial
foreach ( var idPermisoAñadido in permisosAñadidos )
{
await _perfilRepository . LogPermisoAsignacionHistorialAsync ( idPerfil , idPermisoAñadido , idUsuarioModificador , "Asignado" , transaction ) ;
}
foreach ( var idPermisoQuitado in permisosQuitados )
{
await _perfilRepository . LogPermisoAsignacionHistorialAsync ( idPerfil , idPermisoQuitado , idUsuarioModificador , "Removido" , transaction ) ;
}
// --- FIN DE LA LÓGICA DE AUDITORÍA ---
// 4. Actualizar la tabla principal (tu lógica actual)
await _perfilRepository . UpdatePermisosByPerfilIdAsync ( idPerfil , idsNuevos , transaction ) ;
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
transaction . Commit ( ) ;
2025-06-12 19:36:21 -03:00
_logger . LogInformation ( "Permisos actualizados para Perfil ID {IdPerfil} por Usuario ID {IdUsuarioModificador}. Añadidos: {CountAdded}, Quitados: {CountRemoved}" ,
idPerfil , idUsuarioModificador , permisosAñadidos . Count , permisosQuitados . Count ) ;
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
return ( true , null ) ;
}
catch ( Exception ex )
{
try { transaction . Rollback ( ) ; } catch ( Exception rbEx ) { _logger . LogError ( rbEx , "Error rollback ActualizarPermisosAsignadosAsync." ) ; }
_logger . LogError ( ex , "Error al actualizar permisos para Perfil ID: {IdPerfil}" , idPerfil ) ;
return ( false , $"Error interno al actualizar los permisos del perfil: {ex.Message}" ) ;
}
}
2025-06-12 19:36:21 -03:00
public async Task < IEnumerable < PerfilHistorialDto > > ObtenerHistorialAsync (
DateTime ? fechaDesde , DateTime ? fechaHasta ,
int? idUsuarioModifico , string? tipoModificacion ,
int? idPerfilAfectado )
{
var historialData = await _perfilRepository . GetHistorialAsync ( fechaDesde , fechaHasta , idUsuarioModifico , tipoModificacion , idPerfilAfectado ) ;
return historialData . Select ( h = > new PerfilHistorialDto
{
IdPerfil = h . Historial . IdPerfil ,
Perfil = h . Historial . Perfil ,
DescPerfil = h . Historial . DescPerfil ,
Id_Usuario = h . Historial . Id_Usuario ,
NombreUsuarioModifico = h . NombreUsuarioModifico ,
FechaMod = h . Historial . FechaMod ,
TipoMod = h . Historial . TipoMod
} ) . ToList ( ) ;
}
public async Task < IEnumerable < PermisosPerfilesHistorialDto > > ObtenerPermisosAsignadosHistorialAsync (
DateTime ? fechaDesde , DateTime ? fechaHasta ,
int? idUsuarioModifico , string? tipoModificacion ,
int? idPerfilAfectado , int? idPermisoAfectado )
{
var historialData = await _perfilRepository . GetPermisosAsignadosHistorialAsync ( fechaDesde , fechaHasta , idUsuarioModifico , tipoModificacion , idPerfilAfectado , idPermisoAfectado ) ;
return historialData . Select ( h = > new PermisosPerfilesHistorialDto
{
IdHistorial = h . Historial . Id ,
IdPerfil = h . Historial . idPerfil ,
NombrePerfil = h . NombrePerfil ,
IdPermiso = h . Historial . idPermiso ,
DescPermiso = h . DescPermiso ,
CodAccPermiso = h . CodAccPermiso ,
Id_Usuario = h . Historial . Id_Usuario ,
NombreUsuarioModifico = h . NombreUsuarioModifico ,
FechaMod = h . Historial . FechaMod ,
TipoMod = h . Historial . TipoMod
} ) . ToList ( ) ;
}
feat: Implementación CRUD Canillitas, Distribuidores y Precios de Publicación
Backend API:
- Canillitas (`dist_dtCanillas`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Lógica para manejo de `Accionista`, `Baja`, `FechaBaja`.
- Auditoría en `dist_dtCanillas_H`.
- Validación de legajo único y lógica de empresa vs accionista.
- Distribuidores (`dist_dtDistribuidores`):
- Implementado CRUD completo (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Auditoría en `dist_dtDistribuidores_H`.
- Creación de saldos iniciales para el nuevo distribuidor en todas las empresas.
- Verificación de NroDoc único y Nombre opcionalmente único.
- Precios de Publicación (`dist_Precios`):
- Implementado CRUD básico (Modelos, DTOs, Repositorio, Servicio, Controlador).
- Endpoints anidados bajo `/publicaciones/{idPublicacion}/precios`.
- Lógica de negocio para cerrar período de precio anterior al crear uno nuevo.
- Lógica de negocio para reabrir período de precio anterior al eliminar el último.
- Auditoría en `dist_Precios_H`.
- Auditoría en Eliminación de Publicaciones:
- Extendido `PublicacionService.EliminarAsync` para eliminar en cascada registros de precios, recargos, porcentajes de pago (distribuidores y canillitas) y secciones de publicación.
- Repositorios correspondientes (`PrecioRepository`, `RecargoZonaRepository`, `PorcPagoRepository`, `PorcMonCanillaRepository`, `PubliSeccionRepository`) actualizados con métodos `DeleteByPublicacionIdAsync` que registran en sus respectivas tablas `_H` (si existen y se implementó la lógica).
- Asegurada la correcta propagación del `idUsuario` para la auditoría en cascada.
- Correcciones de Nulabilidad:
- Ajustados los métodos `MapToDto` y su uso en `CanillaService` y `PublicacionService` para manejar correctamente tipos anulables.
Frontend React:
- Canillitas:
- `canillaService.ts`.
- `CanillaFormModal.tsx` con selectores para Zona y Empresa, y lógica de Accionista.
- `GestionarCanillitasPage.tsx` con filtros, paginación, y acciones (editar, toggle baja).
- Distribuidores:
- `distribuidorService.ts`.
- `DistribuidorFormModal.tsx` con múltiples campos y selector de Zona.
- `GestionarDistribuidoresPage.tsx` con filtros, paginación, y acciones (editar, eliminar).
- Precios de Publicación:
- `precioService.ts`.
- `PrecioFormModal.tsx` para crear/editar períodos de precios (VigenciaD, VigenciaH opcional, precios por día).
- `GestionarPreciosPublicacionPage.tsx` accesible desde la gestión de publicaciones, para listar y gestionar los períodos de precios de una publicación específica.
- Layout:
- Reemplazado el uso de `Grid` por `Box` con Flexbox en `CanillaFormModal`, `GestionarCanillitasPage` (filtros), `DistribuidorFormModal` y `PrecioFormModal` para resolver problemas de tipos y mejorar la consistencia del layout de formularios.
- Navegación:
- Actualizadas las rutas y pestañas para los nuevos módulos y sub-módulos.
2025-05-20 12:38:55 -03:00
}
}