using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MotoresArgentinosV2.Core.DTOs; using MotoresArgentinosV2.Core.Interfaces; using MotoresArgentinosV2.Infrastructure.Data; using System.Data; namespace MotoresArgentinosV2.Infrastructure.Services; public class AvisosLegacyService : IAvisosLegacyService { private readonly EldiaDbContext _context; private readonly ILogger _logger; public AvisosLegacyService(EldiaDbContext context, ILogger logger) { _context = context; _logger = logger; } public async Task> ObtenerDatosAvisosAsync(string tarea, int paquete = 0) { var resultados = new List(); try { // Usamos ADO.NET manual para tener control total sobre columnas faltantes using (var command = _context.Database.GetDbConnection().CreateCommand()) { command.CommandText = "dbo.spDatosAvisos"; command.CommandType = CommandType.StoredProcedure; var p1 = command.CreateParameter(); p1.ParameterName = "@tarea"; string tareaSafe = tarea ?? string.Empty; if (tareaSafe.Length > 20) { tareaSafe = tareaSafe.Substring(0, 20); } p1.Value = tareaSafe; command.Parameters.Add(p1); // Segundo parámetro var p2 = command.CreateParameter(); p2.ParameterName = "@paquete"; p2.Value = paquete; command.Parameters.Add(p2); await _context.Database.OpenConnectionAsync(); using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var dto = new DatosAvisoDto(); // Usamos helpers seguros que devuelven 0 o "" si la columna no existe o es null // IDs y Básicos dto.IdTipoavi = GetByte(reader, "ID_TIPOAVI"); dto.IdRubro = GetShort(reader, "ID_RUBRO"); dto.IdSubrubro = GetByte(reader, "ID_SUBRUBRO"); // Strings dto.Nomavi = GetString(reader, "NOMAVI"); dto.Textoavi = GetString(reader, "TEXTOAVI"); dto.Descripcion = GetString(reader, "DESCRIPCION"); // Integers (Configuración) dto.IdCombinado = GetInt(reader, "ID_COMBINADO"); dto.PorcentajeCombinado = GetInt(reader, "PORCENTAJE_COMBINADO"); dto.CantidadDias = GetInt(reader, "CANTIDAD_DIAS"); dto.DiasCorridos = GetInt(reader, "DIAS_CORRIDOS"); dto.Palabras = GetInt(reader, "PALABRAS"); dto.Centimetros = GetInt(reader, "CENTIMETROS"); dto.Columnas = GetInt(reader, "COLUMNAS"); dto.TotalAvisos = GetInt(reader, "TOTAL_AVISOS"); dto.Destacado = GetInt(reader, "DESTACADO"); dto.Paquete = GetInt(reader, "PAQUETE"); // Decimales (Precios) dto.ImporteSiniva = GetDecimal(reader, "IMPORTE_SINIVA"); // AQUÍ ESTABA EL PROBLEMA: // Si EMOTOS no trae esta columna, el helper devolverá 0 y no fallará. dto.ImporteTotsiniva = GetDecimal(reader, "IMPORTE_TOTSINIVA"); // Lógica de Negocio Fallback: // Si el SP no calculó el total (columna faltante o 0), y tenemos el neto, lo calculamos nosotros. if (dto.ImporteTotsiniva == 0 && dto.ImporteSiniva > 0) { // Asumimos recargo del 30% si es destacado (según lógica del SP leída) // O simplemente tomamos el neto si es simple. // Esto es un parche seguro para visualización. dto.ImporteTotsiniva = dto.ImporteSiniva; } resultados.Add(dto); } } } return resultados; } catch (Exception ex) { _logger.LogError(ex, "Error crítico ejecutando spDatosAvisos Manual. Tarea: {Tarea}", tarea); throw; } finally { _context.Database.CloseConnection(); } } // --- Helpers de Lectura Tolerante a Fallos --- // Intentan leer la columna. Si no existe (IndexOutOfRange) o es DBNull, devuelven valor default. private byte GetByte(System.Data.Common.DbDataReader reader, string col) { try { return Convert.ToByte(reader[col]); } catch { return 0; } } private short GetShort(System.Data.Common.DbDataReader reader, string col) { try { return Convert.ToInt16(reader[col]); } catch { return 0; } } private int GetInt(System.Data.Common.DbDataReader reader, string col) { try { return Convert.ToInt32(reader[col]); } catch { return 0; } } private decimal GetDecimal(System.Data.Common.DbDataReader reader, string col) { try { return Convert.ToDecimal(reader[col]); } catch { return 0; } } private string GetString(System.Data.Common.DbDataReader reader, string col) { try { return reader[col]?.ToString() ?? ""; } catch { return ""; } } // --- Resto de métodos (Mantener igual) --- public async Task InsertarAvisoAsync(InsertarAvisoDto dto) { try { var parameters = new[] { new SqlParameter("@tipo", dto.Tipo), new SqlParameter("@nro_operacion", dto.NroOperacion), new SqlParameter("@id_cliente", dto.IdCliente), new SqlParameter("@tipodoc", dto.Tipodoc), new SqlParameter("@nro_doc", dto.NroDoc), new SqlParameter("@razon", dto.Razon), new SqlParameter("@calle", dto.Calle), new SqlParameter("@numero", dto.Numero), new SqlParameter("@localidad", dto.Localidad), new SqlParameter("@codigopostal", dto.CodigoPostal), new SqlParameter("@telefono", dto.Telefono), new SqlParameter("@email", dto.Email), new SqlParameter("@id_tipoiva", dto.IdTipoiva), new SqlParameter("@porcentaje_iva1", dto.PorcentajeIva1), new SqlParameter("@porcentaje_iva2", dto.PorcentajeIva2), new SqlParameter("@porcentaje_percepcion", dto.PorcentajePercepcion), new SqlParameter("@id_tipoaviso", dto.IdTipoaviso), new SqlParameter("@nombreaviso", dto.Nombreaviso), new SqlParameter("@id_rubro", dto.IdRubro), new SqlParameter("@id_subrubro", dto.IdSubrubro), new SqlParameter("@id_combinado", dto.IdCombinado), new SqlParameter("@porcentaje_combinado", dto.PorcentajeCombinado), new SqlParameter("@fecha_inicio", dto.FechaInicio), new SqlParameter("@cant_dias", dto.CantDias), new SqlParameter("@dias_corridos", dto.DiasCorridos), new SqlParameter("@palabras", dto.Palabras), new SqlParameter("@centimetros", dto.Centimetros), new SqlParameter("@columnas", dto.Columnas), new SqlParameter("@id_tarjeta", dto.IdTarjeta), new SqlParameter("@nro_tarjeta", dto.NroTarjeta), new SqlParameter("@cvc_tarjeta", dto.CvcTarjeta), new SqlParameter("@vencimiento", dto.Vencimiento), new SqlParameter("@calle_envio", dto.CalleEnvio), new SqlParameter("@numero_envio", dto.NumeroEnvio), new SqlParameter("@localidad_envio", dto.LocalidadEnvio), new SqlParameter("@tarifa", dto.Tarifa), new SqlParameter("@importe_aviso", dto.ImporteAviso), new SqlParameter("@importe_iva1", dto.ImporteIva1), new SqlParameter("@importe_iva2", dto.ImporteIva2), new SqlParameter("@importe_percepcion", dto.ImportePercepcion), new SqlParameter("@cantavi", dto.Cantavi), new SqlParameter("@paquete", dto.Paquete), new SqlParameter("@destacado", dto.Destacado) }; await _context.Database.ExecuteSqlRawAsync( "EXEC dbo.spInsertaAvisos @tipo, @nro_operacion, @id_cliente, @tipodoc, @nro_doc, @razon, " + "@calle, @numero, @localidad, @codigopostal, @telefono, @email, @id_tipoiva, @porcentaje_iva1, " + "@porcentaje_iva2, @porcentaje_percepcion, @id_tipoaviso, @nombreaviso, @id_rubro, @id_subrubro, " + "@id_combinado, @porcentaje_combinado, @fecha_inicio, @cant_dias, @dias_corridos, @palabras, " + "@centimetros, @columnas, @id_tarjeta, @nro_tarjeta, @cvc_tarjeta, @vencimiento, @calle_envio, " + "@numero_envio, @localidad_envio, @tarifa, @importe_aviso, @importe_iva1, @importe_iva2, " + "@importe_percepcion, @cantavi, @paquete, @destacado", parameters); return true; } catch (Exception ex) { _logger.LogError(ex, "Error al ejecutar spInsertaAvisos"); throw; } } public async Task> ObtenerTarifasAsync(string formulario, int paquete) { return await ObtenerDatosAvisosAsync(formulario, paquete); } public async Task> ObtenerAvisosPorClienteAsync(string nroDoc) { try { var sql = @" SELECT nombreaviso as NombreAviso, fecha_inicio as FechaInicio, importe_aviso as ImporteAviso, estado as Estado, nro_operacion as NroOperacion FROM dbo.AVISOSWEB WHERE nro_doc = @nroDoc ORDER BY fecha_inicio DESC"; var paramDoc = new SqlParameter("@nroDoc", nroDoc); var resultado = await _context.Database .SqlQueryRaw(sql, paramDoc) .ToListAsync(); return resultado; } catch (Exception ex) { _logger.LogError(ex, "Error al obtener avisos para el documento: {NroDocumento}", nroDoc); return new List(); } } }