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  Dapper ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  GestionIntegral.Api.Models.Distribucion ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  Microsoft.Extensions.Logging ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  System.Collections.Generic ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  System.Data ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  System.Linq ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  System.Text ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  System.Threading.Tasks ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  GestionIntegral.Api.Data.Repositories.Distribucion  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  class  OtroDestinoRepository  :  IOtroDestinoRepository 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        private  readonly  DbConnectionFactory  _connectionFactory ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        private  readonly  ILogger < OtroDestinoRepository >  _logger ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  OtroDestinoRepository ( DbConnectionFactory  connectionFactory ,  ILogger < OtroDestinoRepository >  logger ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            _connectionFactory  =  connectionFactory ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            _logger  =  logger ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < IEnumerable < OtroDestino > >  GetAllAsync ( string?  nombreFilter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  sqlBuilder  =  new  StringBuilder ( "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE 1=1" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  parameters  =  new  DynamicParameters ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ! string . IsNullOrWhiteSpace ( nombreFilter ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                sqlBuilder . Append ( " AND Nombre LIKE @NombreFilter" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                parameters . Add ( "NombreFilter" ,  $"%{nombreFilter}%" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sqlBuilder . Append ( " ORDER BY Nombre;" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  await  connection . QueryAsync < OtroDestino > ( sqlBuilder . ToString ( ) ,  parameters ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                _logger . LogError ( ex ,  "Error al obtener todos los Otros Destinos. Filtro: {Nombre}" ,  nombreFilter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  Enumerable . Empty < OtroDestino > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < OtroDestino ? >  GetByIdAsync ( int  id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sql  =  "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  await  connection . QuerySingleOrDefaultAsync < OtroDestino > ( sql ,  new  {  Id  =  id  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                _logger . LogError ( ex ,  "Error al obtener Otro Destino por ID: {IdDestino}" ,  id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < bool >  ExistsByNameAsync ( string  nombre ,  int?  excludeId  =  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  sqlBuilder  =  new  StringBuilder ( "SELECT COUNT(1) FROM dbo.dist_dtOtrosDestinos WHERE Nombre = @Nombre" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  parameters  =  new  DynamicParameters ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            parameters . Add ( "Nombre" ,  nombre ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( excludeId . HasValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                sqlBuilder . Append ( " AND Id_Destino != @ExcludeId" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                parameters . Add ( "ExcludeId" ,  excludeId . Value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                var  count  =  await  connection . ExecuteScalarAsync < int > ( sqlBuilder . ToString ( ) ,  parameters ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  count  >  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                _logger . LogError ( ex ,  "Error en ExistsByNameAsync para Otro Destino con nombre: {Nombre}" ,  nombre ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < bool >  IsInUseAsync ( int  id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlCheckSalidas  =  "SELECT TOP 1 1 FROM dbo.dist_SalidasOtrosDestinos WHERE Id_Destino = @IdDestino" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                var  inUse  =  await  connection . ExecuteScalarAsync < int? > ( sqlCheckSalidas ,  new  {  IdDestino  =  id  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  inUse . HasValue  & &  inUse . Value  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                _logger . LogError ( ex ,  "Error en IsInUseAsync para Otro Destino ID: {IdDestino}" ,  id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < OtroDestino ? >  CreateAsync ( OtroDestino  nuevoDestino ,  int  idUsuario ,  IDbTransaction  transaction ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlInsert  =  @ "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                INSERT  INTO  dbo . dist_dtOtrosDestinos  ( Nombre ,  Obs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                OUTPUT  INSERTED . Id_Destino  AS  IdDestino ,  INSERTED . Nombre ,  INSERTED . Obs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                VALUES  ( @Nombre ,  @Obs ) ; ";
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlInsertHistorico  =  @ "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                INSERT  INTO  dbo . dist_dtOtrosDestinos_H  ( Id_Destino ,  Nombre ,  Obs ,  Id_Usuario ,  FechaMod ,  TipoMod ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                VALUES  ( @IdDestino ,  @Nombre ,  @Obs ,  @IdUsuario ,  @FechaMod ,  @TipoMod ) ; ";
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  connection  =  transaction . Connection ! ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  insertedDestino  =  await  connection . QuerySingleAsync < OtroDestino > ( sqlInsert ,  nuevoDestino ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( insertedDestino  = =  null  | |  insertedDestino . IdDestino  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                throw  new  DataException ( "No se pudo obtener el ID del otro destino insertado." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  connection . ExecuteAsync ( sqlInsertHistorico ,  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdDestino  =  insertedDestino . IdDestino , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                insertedDestino . Nombre , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                insertedDestino . Obs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdUsuario  =  idUsuario , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                FechaMod  =  DateTime . Now , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                TipoMod  =  "Insertada" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  insertedDestino ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < bool >  UpdateAsync ( OtroDestino  destinoAActualizar ,  int  idUsuario ,  IDbTransaction  transaction ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  connection  =  transaction . Connection ! ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  destinoActual  =  await  connection . QuerySingleOrDefaultAsync < OtroDestino > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                new  {  Id  =  destinoAActualizar . IdDestino  } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( destinoActual  = =  null )  throw  new  KeyNotFoundException ( $"Otro Destino con ID {destinoAActualizar.IdDestino} no encontrado." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlUpdate  =  "UPDATE dbo.dist_dtOtrosDestinos SET Nombre = @Nombre, Obs = @Obs WHERE Id_Destino = @IdDestino;" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlInsertHistorico  =  @ "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                INSERT  INTO  dbo . dist_dtOtrosDestinos_H  ( Id_Destino ,  Nombre ,  Obs ,  Id_Usuario ,  FechaMod ,  TipoMod ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                VALUES  ( @IdDestino ,  @NombreActual ,  @ObsActual ,  @IdUsuario ,  @FechaMod ,  @TipoMod ) ; ";
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  connection . ExecuteAsync ( sqlInsertHistorico ,  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdDestino  =  destinoActual . IdDestino , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                NombreActual  =  destinoActual . Nombre , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ObsActual  =  destinoActual . Obs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdUsuario  =  idUsuario , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                FechaMod  =  DateTime . Now , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                TipoMod  =  "Modificada" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  rowsAffected  =  await  connection . ExecuteAsync ( sqlUpdate ,  destinoAActualizar ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  rowsAffected  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < bool >  DeleteAsync ( int  id ,  int  idUsuario ,  IDbTransaction  transaction ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  connection  =  transaction . Connection ! ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  destinoActual  =  await  connection . QuerySingleOrDefaultAsync < OtroDestino > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                new  {  Id  =  id  } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( destinoActual  = =  null )  throw  new  KeyNotFoundException ( $"Otro Destino con ID {id} no encontrado." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlDelete  =  "DELETE FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  string  sqlInsertHistorico  =  @ "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                INSERT  INTO  dbo . dist_dtOtrosDestinos_H  ( Id_Destino ,  Nombre ,  Obs ,  Id_Usuario ,  FechaMod ,  TipoMod ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                VALUES  ( @IdDestino ,  @Nombre ,  @Obs ,  @IdUsuario ,  @FechaMod ,  @TipoMod ) ; ";
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  connection . ExecuteAsync ( sqlInsertHistorico ,  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdDestino  =  destinoActual . IdDestino , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                destinoActual . Nombre , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                destinoActual . Obs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                IdUsuario  =  idUsuario , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                FechaMod  =  DateTime . Now , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                TipoMod  =  "Eliminada" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  rowsAffected  =  await  connection . ExecuteAsync ( sqlDelete ,  new  {  Id  =  id  } ,  transaction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  rowsAffected  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-12 19:36:21 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        public  async  Task < IEnumerable < ( OtroDestinoHistorico  Historial ,  string  NombreUsuarioModifico ) > >  GetHistorialAsync ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            DateTime ?  fechaDesde ,  DateTime ?  fechaHasta , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            int?  idUsuarioModifico ,  string?  tipoModificacion , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            int?  idOtroDestinoOriginal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            using  var  connection  =  _connectionFactory . CreateConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  sqlBuilder  =  new  StringBuilder ( @ "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    h . Id_Destino ,  h . Nombre ,  h . Obs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    h . Id_Usuario ,  h . FechaMod ,  h . TipoMod , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    u . Nombre  +  ' '  +  u . Apellido  AS  NombreUsuarioModifico 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                FROM  dbo . dist_dtOtrosDestinos_H  h 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                JOIN  dbo . gral_Usuarios  u  ON  h . Id_Usuario  =  u . Id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                WHERE  1 = 1 ");
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            var  parameters  =  new  DynamicParameters ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( fechaDesde . HasValue )  {  sqlBuilder . Append ( " AND h.FechaMod >= @FechaDesdeParam" ) ;  parameters . Add ( "FechaDesdeParam" ,  fechaDesde . Value . Date ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( fechaHasta . HasValue )  {  sqlBuilder . Append ( " AND h.FechaMod <= @FechaHastaParam" ) ;  parameters . Add ( "FechaHastaParam" ,  fechaHasta . Value . Date . AddDays ( 1 ) . AddTicks ( - 1 ) ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( idUsuarioModifico . HasValue )  {  sqlBuilder . Append ( " AND h.Id_Usuario = @IdUsuarioModificoParam" ) ;  parameters . Add ( "IdUsuarioModificoParam" ,  idUsuarioModifico . Value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ! string . IsNullOrWhiteSpace ( tipoModificacion ) )  {  sqlBuilder . Append ( " AND h.TipoMod = @TipoModParam" ) ;  parameters . Add ( "TipoModParam" ,  tipoModificacion ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( idOtroDestinoOriginal . HasValue )  {  sqlBuilder . Append ( " AND h.Id_Destino = @IdOtroDestinoOriginalParam" ) ;  parameters . Add ( "IdOtroDestinoOriginalParam" ,  idOtroDestinoOriginal . Value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sqlBuilder . Append ( " ORDER BY h.FechaMod DESC;" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                var  result  =  await  connection . QueryAsync < OtroDestinoHistorico ,  string ,  ( OtroDestinoHistorico ,  string ) > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    sqlBuilder . ToString ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ( hist ,  userName )  = >  ( hist ,  userName ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    parameters , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    splitOn :  "NombreUsuarioModifico" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            catch  ( Exception  ex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                _logger . LogError ( ex ,  "Error al obtener historial de Otros Destinos (Maestro)." ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  Enumerable . Empty < ( OtroDestinoHistorico ,  string ) > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
											 
										
											
												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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}