Backend API: - Implementado CRUD completo para Empresas (DE001-DE004): - EmpresaRepository, EmpresaService, EmpresasController. - Lógica de creación/eliminación de saldos iniciales en EmpresaService. - Transacciones y registro en tablas _H. - Verificación de permisos específicos. - Implementado CRUD completo para Plantas de Impresión (IP001-IP004): - PlantaRepository, PlantaService, PlantasController. - Transacciones y registro en tablas _H. - Verificación de permisos. - Implementado CRUD completo para Tipos de Bobina (IB006-IB009): - TipoBobinaRepository, TipoBobinaService, TiposBobinaController. - Transacciones y registro en tablas _H. - Verificación de permisos. - Implementado CRUD completo para Estados de Bobina (IB010-IB013): - EstadoBobinaRepository, EstadoBobinaService, EstadosBobinaController. - Transacciones y registro en tablas _H. - Verificación de permisos. Frontend React: - Módulo Empresas: - empresaService.ts para interactuar con la API. - EmpresaFormModal.tsx para crear/editar empresas. - GestionarEmpresasPage.tsx con tabla, filtro, paginación y menú de acciones. - Integración con el hook usePermissions para control de acceso. - Módulo Plantas de Impresión: - plantaService.ts. - PlantaFormModal.tsx. - GestionarPlantasPage.tsx con tabla, filtro, paginación y acciones. - Integración con usePermissions. - Módulo Tipos de Bobina: - tipoBobinaService.ts. - TipoBobinaFormModal.tsx. - GestionarTiposBobinaPage.tsx con tabla, filtro, paginación y acciones. - Integración con usePermissions. - Módulo Estados de Bobina: - estadoBobinaService.ts. - EstadoBobinaFormModal.tsx. - GestionarEstadosBobinaPage.tsx con tabla, filtro, paginación y acciones. - Integración con usePermissions. - Navegación: - Añadidas sub-pestañas y rutas para los nuevos módulos dentro de "Distribución" (Empresas) e "Impresión" (Plantas, Tipos Bobina, Estados Bobina). - Creado ImpresionIndexPage.tsx para la navegación interna del módulo de Impresión. Correcciones: - Corregido el uso de CommitAsync/RollbackAsync a Commit/Rollback síncronos en PlantaService.cs debido a que IDbTransaction no los soporta asíncronamente.
		
			
				
	
	
		
			134 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Dapper;
 | |
| using GestionIntegral.Api.Data.Repositories; 
 | |
| using GestionIntegral.Api.Models;
 | |
| using Microsoft.Extensions.Logging;
 | |
| using System.Collections.Generic;
 | |
| using System.Data;
 | |
| using System.Threading.Tasks;
 | |
| 
 | |
| namespace GestionIntegral.Api.Data.Repositories.Contables
 | |
| {
 | |
|     public class SaldoRepository : ISaldoRepository
 | |
|     {
 | |
|         private readonly DbConnectionFactory _connectionFactory;
 | |
|         private readonly ILogger<SaldoRepository> _logger;
 | |
| 
 | |
|         public SaldoRepository(DbConnectionFactory connectionFactory, ILogger<SaldoRepository> logger)
 | |
|         {
 | |
|             _connectionFactory = connectionFactory;
 | |
|             _logger = logger;
 | |
|         }
 | |
| 
 | |
|         public async Task<IEnumerable<int>> GetAllDistribuidorIdsAsync()
 | |
|         {
 | |
|             var sql = "SELECT Id_Distribuidor FROM dbo.dist_dtDistribuidores";
 | |
|             try
 | |
|             {
 | |
|                 using (var connection = _connectionFactory.CreateConnection())
 | |
|                 {
 | |
|                     return await connection.QueryAsync<int>(sql);
 | |
|                 }
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 _logger.LogError(ex, "Error al obtener IDs de Distribuidores.");
 | |
|                 return Enumerable.Empty<int>();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public async Task<bool> CreateSaldoInicialAsync(string destino, int idDestino, int idEmpresa, IDbTransaction transaction)
 | |
|         {
 | |
|             var sql = @"
 | |
|                 INSERT INTO dbo.cue_Saldos (Destino, Id_Destino, Monto, Id_Empresa)
 | |
|                 VALUES (@Destino, @IdDestino, 0.00, @IdEmpresa);";
 | |
|             try
 | |
|             {
 | |
|                 int rowsAffected = await transaction.Connection!.ExecuteAsync(sql, // Añadir !
 | |
|                     new { Destino = destino, IdDestino = idDestino, IdEmpresa = idEmpresa },
 | |
|                     transaction: transaction);
 | |
|                 return rowsAffected == 1;
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 _logger.LogError(ex, "Error al insertar saldo inicial para {Destino} ID {IdDestino}, Empresa ID {IdEmpresa}.", destino, idDestino, idEmpresa);
 | |
|                 throw;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public async Task<bool> DeleteSaldosByEmpresaAsync(int idEmpresa, IDbTransaction transaction)
 | |
|         {
 | |
|              var sql = "DELETE FROM dbo.cue_Saldos WHERE Id_Empresa = @IdEmpresa";
 | |
|              try
 | |
|              {
 | |
|                  await transaction.Connection!.ExecuteAsync(sql, new { IdEmpresa = idEmpresa }, transaction: transaction);
 | |
|                  return true; // Asumir éxito si no hay excepción
 | |
|              }
 | |
|              catch (Exception ex)
 | |
|              {
 | |
|                  _logger.LogError(ex, "Error al eliminar saldos para Empresa ID {IdEmpresa}.", idEmpresa);
 | |
|                  throw;
 | |
|              }
 | |
|         }
 | |
| 
 | |
|         public async Task<bool> ModificarSaldoAsync(string destino, int idDestino, int idEmpresa, decimal montoAAgregar, IDbTransaction? transaction = null)
 | |
|          {
 | |
|              var sql = @"UPDATE dbo.cue_Saldos
 | |
|                          SET Monto = Monto + @MontoAAgregar
 | |
|                          WHERE Destino = @Destino AND Id_Destino = @IdDestino AND Id_Empresa = @IdEmpresa;";
 | |
| 
 | |
|             // Usar una variable para la conexión para poder aplicar el '!' si es necesario
 | |
|              IDbConnection connection = transaction?.Connection ?? _connectionFactory.CreateConnection();
 | |
|              bool ownConnection = transaction == null; // Saber si necesitamos cerrar la conexión nosotros
 | |
| 
 | |
|              try
 | |
|              {
 | |
|                  if (ownConnection) await (connection as System.Data.Common.DbConnection)!.OpenAsync(); // Abrir solo si no hay transacción externa
 | |
| 
 | |
|                  var parameters = new {
 | |
|                      MontoAAgregar = montoAAgregar,
 | |
|                      Destino = destino,
 | |
|                      IdDestino = idDestino,
 | |
|                      IdEmpresa = idEmpresa
 | |
|                  };
 | |
|                  // Aplicar '!' aquí también si viene de la transacción
 | |
|                  int rowsAffected = await connection.ExecuteAsync(sql, parameters, transaction: transaction);
 | |
|                  return rowsAffected == 1;
 | |
|              }
 | |
|              catch (Exception ex)
 | |
|              {
 | |
|                  _logger.LogError(ex, "Error al modificar saldo para {Destino} ID {IdDestino}, Empresa ID {IdEmpresa}.", destino, idDestino, idEmpresa);
 | |
|                   if (transaction != null) throw; // Re-lanzar si estamos en una transacción externa
 | |
|                   return false; // Devolver false si fue una operación aislada que falló
 | |
|              }
 | |
|              finally
 | |
|              {
 | |
|                  // Cerrar la conexión solo si la abrimos nosotros (no había transacción externa)
 | |
|                  if (ownConnection && connection.State == ConnectionState.Open)
 | |
|                  {
 | |
|                      await (connection as System.Data.Common.DbConnection)!.CloseAsync();
 | |
|                  }
 | |
|                  // Disponer de la conexión si la creamos nosotros
 | |
|                  if(ownConnection) (connection as IDisposable)?.Dispose();
 | |
|              }
 | |
|          }
 | |
|          public async Task<bool> CheckIfSaldosExistForEmpresaAsync(int idEmpresa)
 | |
|         {
 | |
|             var sql = "SELECT COUNT(1) FROM dbo.cue_Saldos WHERE Id_Empresa = @IdEmpresa";
 | |
|             try
 | |
|             {
 | |
|                 // Este método es de solo lectura, no necesita transacción externa normalmente
 | |
|                 using (var connection = _connectionFactory.CreateConnection())
 | |
|                 {
 | |
|                     var count = await connection.ExecuteScalarAsync<int>(sql, new { IdEmpresa = idEmpresa });
 | |
|                     return count > 0; // Devuelve true si hay al menos un saldo
 | |
|                 }
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 _logger.LogError(ex, "Error en CheckIfSaldosExistForEmpresaAsync para Empresa ID {IdEmpresa}", idEmpresa);
 | |
|                 return false; // Asumir que no existen si hay error, para no bloquear la eliminación innecesariamente
 | |
|                               // O podrías devolver true para ser más conservador si la verificación es crítica.
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |