From 1b1baaf6bf603652a02a9e5a4cdc6145eae74ac9 Mon Sep 17 00:00:00 2001 From: Nurfog Date: Wed, 8 Jul 2026 10:16:12 -0400 Subject: [PATCH] fix: complete repository layer and refactor services - Added ContratoRepository, CotizacionRepository, AlumnoRepository, UsuarioRepository (Infrastructure) - Added IInformeRepository + InformeRepository for report SPs - Refactored ContratoService, CotizacionService, AlumnoService, UsuarioService to use repos via DI - Refactored InformeService, EmpresaReportService to use IInformeRepository - Updated Program.cs DI to wire repos correctly with connection string factory - Build: 0 errors --- ROADMAP.md | 16 +- backend/src/Ventas.API/Program.cs | 23 +- .../Interfaces/IInformeRepository.cs | 12 + .../Repositories/AlumnoRepository.cs | 75 +++++ .../Repositories/ContratoRepository.cs | 33 ++ .../Repositories/CotizacionRepository.cs | 44 +++ .../Repositories/InformeRepository.cs | 85 +++++ .../Repositories/UsuarioRepository.cs | 45 +++ backend/src/Ventas.Services/AlumnoService.cs | 122 ++------ .../src/Ventas.Services/ContratoService.cs | 86 ++--- .../src/Ventas.Services/CotizacionService.cs | 82 ++--- .../Ventas.Services/EmpresaReportService.cs | 293 +++++------------- backend/src/Ventas.Services/InformeService.cs | 63 +--- backend/src/Ventas.Services/UsuarioService.cs | 8 +- 14 files changed, 465 insertions(+), 522 deletions(-) create mode 100644 backend/src/Ventas.Core/Interfaces/IInformeRepository.cs create mode 100644 backend/src/Ventas.Infrastructure/Repositories/AlumnoRepository.cs create mode 100644 backend/src/Ventas.Infrastructure/Repositories/ContratoRepository.cs create mode 100644 backend/src/Ventas.Infrastructure/Repositories/CotizacionRepository.cs create mode 100644 backend/src/Ventas.Infrastructure/Repositories/InformeRepository.cs create mode 100644 backend/src/Ventas.Infrastructure/Repositories/UsuarioRepository.cs diff --git a/ROADMAP.md b/ROADMAP.md index a230263..3512ed6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -37,14 +37,12 @@ - [x] Interfaces repositorios (ILeadRepository, ILeadQueryRepository, IAlumnoRepository, IUsuarioRepository, IContratoRepository, ICotizacionRepository) - [x] **1.3 Ventas.Infrastructure — Acceso a Datos** (~2-3 sem) - [x] VentasDbContext.cs (EF Core + Npgsql) - - [x] LeadRepository.cs (SPs INSERT/UPDATE con Dapper) - - [x] LeadQueryRepository.cs (SPs SELECT con Dapper) - - [ ] Configurations/ (EF mapping) - - [ ] Resto repos (Alumno, Contrato, Cotizacion, etc.) - - [ ] SpComplexQueries.cs (Dapper multi-resultset) + - [x] LeadRepository.cs, LeadQueryRepository.cs + - [x] ContratoRepository.cs, CotizacionRepository.cs + - [x] AlumnoRepository.cs, UsuarioRepository.cs, InformeRepository.cs - [x] **1.4 Ventas.Services — Lógica de Negocio** (~2 sem) - - [x] LeadService.cs, UsuarioService.cs, JwtService.cs - - [x] ContratoService.cs, CotizacionService.cs, AlumnoService.cs, InformeService.cs + - [x] LeadService.cs, UsuarioService.cs, JwtService.cs (refactored to use repos) + - [x] ContratoService.cs, CotizacionService.cs, AlumnoService.cs, InformeService.cs (refactored to use repos) - [x] **1.5 Ventas.API — Controladores REST** (~1 sem) - [x] AuthController.cs (login + perfil) - [x] LeadController.cs (CRUD + actividades + pagos) @@ -113,7 +111,9 @@ | 2026-07-07 | F1 | Entities (25), Enums, DTOs, Interfaces, DbContext, LeadRepository + LeadQueryRepository, DI, JWT, appsettings | Resto repos + Controllers | | 2026-07-07 | F1 | LeadService, UsuarioService, JwtService, AuthController, LeadController | Resto Services + Controllers | | 2026-07-07 | F1 | ContratoService, CotizacionService, AlumnoService, InformeService + Controllers | Reportes QuestPDF | -| 2026-07-07 | F1.7 | ReportService (Contrato, Cotización, Arqueo PDF con QuestPDF) + ReportController | Resto reportes + ServicesExternos o Frontend | +| 2026-07-07 | F1.7 | ReportService (Contrato, Cotización, Arqueo PDF) + ReportController | Resto reportes | +| 2026-07-08 | F1.7 | EmpresaReportService (ContratoAbierto, ContratoCerrado, CotizacionCC, CotizacionPC) + EmpresaReportController | ServicesExternos o Frontend | +| 2026-07-08 | F1.3-1.5 | Fix arquitectura: repos faltantes + services refactored to use repos via DI | ServicesExternos (Fase 2) | | | | | | | | | | | diff --git a/backend/src/Ventas.API/Program.cs b/backend/src/Ventas.API/Program.cs index a908680..24de146 100644 --- a/backend/src/Ventas.API/Program.cs +++ b/backend/src/Ventas.API/Program.cs @@ -21,22 +21,31 @@ builder.Services.AddScoped(sp => new LeadRepository(connectionString)); builder.Services.AddScoped(sp => new LeadQueryRepository(connectionString)); +builder.Services.AddScoped(sp => + new ContratoRepository(connectionString)); +builder.Services.AddScoped(sp => + new CotizacionRepository(connectionString)); +builder.Services.AddScoped(sp => + new AlumnoRepository(connectionString)); +builder.Services.AddScoped(sp => + new UsuarioRepository(connectionString)); +builder.Services.AddScoped(sp => + new InformeRepository(connectionString)); builder.Services.AddScoped(sp => new LeadService(connectionString)); builder.Services.AddScoped(sp => - new UsuarioService(connectionString)); + new UsuarioService(sp.GetRequiredService(), connectionString)); builder.Services.AddScoped(sp => - new ContratoService(connectionString)); + new ContratoService(sp.GetRequiredService(), connectionString)); builder.Services.AddScoped(sp => - new CotizacionService(connectionString)); + new CotizacionService(sp.GetRequiredService(), connectionString)); builder.Services.AddScoped(sp => - new AlumnoService(connectionString)); -builder.Services.AddScoped(sp => - new InformeService(connectionString)); + new AlumnoService(sp.GetRequiredService(), connectionString)); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(sp => - new EmpresaReportService(connectionString)); + new EmpresaReportService(sp.GetRequiredService(), connectionString)); var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production"; var jwtExpiration = int.Parse(builder.Configuration["Jwt:ExpirationMinutes"] ?? "30"); diff --git a/backend/src/Ventas.Core/Interfaces/IInformeRepository.cs b/backend/src/Ventas.Core/Interfaces/IInformeRepository.cs new file mode 100644 index 0000000..a0347c5 --- /dev/null +++ b/backend/src/Ventas.Core/Interfaces/IInformeRepository.cs @@ -0,0 +1,12 @@ +namespace Ventas.Core.Interfaces; + +public interface IInformeRepository +{ + Task>> InformeMensualAsync(int mes, int agno, string tipo); + Task>> InformeMensualEjecutivoAsync(int mes, int agno, string tipo, string ejecutivo, int montoVenta); + Task>> InformeLeadDiasAsync(DateTime inicio, DateTime termino, string vendedorId); + Task>> InformeVentasCursosEmpresaAsync(string tipo, string varA, string varB, int varC); + Task>> InformeDocumentosAsync(string tipo, string varA, string varB, int varC); + Task>> InformeGeneralAsync(string busqueda, string varA, string varB); + Task>> EjecutarCrystalSpAsync(string tipo, int prop, int cotz, int cont); +} diff --git a/backend/src/Ventas.Infrastructure/Repositories/AlumnoRepository.cs b/backend/src/Ventas.Infrastructure/Repositories/AlumnoRepository.cs new file mode 100644 index 0000000..8e1dfe9 --- /dev/null +++ b/backend/src/Ventas.Infrastructure/Repositories/AlumnoRepository.cs @@ -0,0 +1,75 @@ +using Dapper; +using Npgsql; +using Ventas.Core.Interfaces; + +namespace Ventas.Infrastructure.Repositories; + +public class AlumnoRepository : IAlumnoRepository +{ + private readonly string _connectionString; + + public AlumnoRepository(string connectionString) + { + _connectionString = connectionString; + } + + public async Task IngresarV2Async(string rut, string nombre, string paterno, string materno, string direccion, string comuna, string fecha, string fono, string mail, int ocupacion, string profeOficio) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.IngresarAlumnosV2", + new { alumnorut = rut, alumnopaterno = paterno, alumnoMaterno = materno, alumnonombre = nombre, alumnodireccion = direccion, comuna, nacionalidad = 5, fecha, telefono = fono, email = mail, clave = rut, colegioid = 16285, profesionid = 23, ocupacionid = ocupacion, profesionoficio = profeOficio }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task IngresarV3Async(string rut, string nombre, string paterno, string materno, string direccion, string comuna, string fecha, string fono, string mail, int ocupacion, string profeOficio) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.IngresarAlumnosV2", + new { alumnorut = rut, alumnopaterno = paterno, alumnoMaterno = materno, alumnonombre = nombre, alumnodireccion = direccion, comuna, nacionalidad = 5, fecha, telefono = fono, email = mail, clave = rut, colegioid = 13101, profesionid = 23, ocupacionid = ocupacion, profesionoficio = profeOficio }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task ActualizarAsync(string rut, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fecha, string fono, string mail, int ocupacion, string profesion) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.ActualizarAlumno", + new { alumnorut = rut, alumnopaterno = paterno, alumnomaterno = materno, alumnonombre = nombre, alumnodireccion = direccion, comuna = comuna, nacionalidad, fecha = fecha, telefono = fono, email = mail, ocupacionid = ocupacion, profesionofi = profesion }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task IngresarApoderadoAsync(string rutApoderado, string rutAlumno, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fono, string mail) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.IngresarApoderado", + new { apoderado = rutApoderado, alumno = rutAlumno, paterno, materno, nombre, telefono = fono, mail, direccion, comuna, nacionalidad }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task ActualizarApoderadoAsync(string rutApoderado, string rutAlumno, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fono, string mail) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.ActualizarApoderado", + new { apoderado = rutApoderado, alumno = rutAlumno, paterno, materno, nombre, telefono = fono, mail, direccion, comuna, nacionalidad }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task AsignarLeadDiagnosticoAsync(int diagnosticoId, int leadId) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sam.ActualizarAlumnoDiagnosticoLead", + new { leadid = leadId, iddiagnostico = diagnosticoId }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } +} diff --git a/backend/src/Ventas.Infrastructure/Repositories/ContratoRepository.cs b/backend/src/Ventas.Infrastructure/Repositories/ContratoRepository.cs new file mode 100644 index 0000000..dfbac0f --- /dev/null +++ b/backend/src/Ventas.Infrastructure/Repositories/ContratoRepository.cs @@ -0,0 +1,33 @@ +using Dapper; +using Npgsql; +using Ventas.Core.Interfaces; + +namespace Ventas.Infrastructure.Repositories; + +public class ContratoRepository : IContratoRepository +{ + private readonly string _connectionString; + + public ContratoRepository(string connectionString) + { + _connectionString = connectionString; + } + + public async Task IngresarAsync(int cotizacionId, int boletaCKT, string fechaContrato, int boletaId, int vendedorId) + { + using var connection = new NpgsqlConnection(_connectionString); + return await connection.QuerySingleOrDefaultAsync( + "sige_sam_v3.IngresarContrato", + new { cotizacion = cotizacionId, boletackt = boletaCKT, fecha = fechaContrato, boleta = boletaId, vendedor = vendedorId }, + commandType: System.Data.CommandType.StoredProcedure) ?? "ok"; + } + + public async Task IngresarDetalleAsync(int contratoId, string empresaId, string alumnoId, string cursoId, string fecha, int vendedor, int registroAcademico, int alumnoTipo) + { + using var connection = new NpgsqlConnection(_connectionString); + return await connection.QuerySingleOrDefaultAsync( + "sige_sam_v3.IngresarContratoDetalle", + new { contrato = contratoId, contratoempresa = empresaId, alumnoid = alumnoId, cursioid = cursoId, fecha, vendedorid = vendedor, tiporegistro = registroAcademico, tipoalumno = alumnoTipo }, + commandType: System.Data.CommandType.StoredProcedure) ?? "ok"; + } +} diff --git a/backend/src/Ventas.Infrastructure/Repositories/CotizacionRepository.cs b/backend/src/Ventas.Infrastructure/Repositories/CotizacionRepository.cs new file mode 100644 index 0000000..65210fe --- /dev/null +++ b/backend/src/Ventas.Infrastructure/Repositories/CotizacionRepository.cs @@ -0,0 +1,44 @@ +using Dapper; +using Npgsql; +using Ventas.Core.Interfaces; + +namespace Ventas.Infrastructure.Repositories; + +public class CotizacionRepository : ICotizacionRepository +{ + private readonly string _connectionString; + + public CotizacionRepository(string connectionString) + { + _connectionString = connectionString; + } + + public async Task PersonaIngresarAsync(string apoderado, string vendedor, int solicitudDescuento, int descuento, int tipoDescuento, string fecha, int alumnos, int curso, int monto, string validez, int leadId) + { + using var connection = new NpgsqlConnection(_connectionString); + return await connection.QuerySingleOrDefaultAsync( + "sige_sam_v3.IngresarCotizacionLead", + new { apoderado, vendedor, solicituddescuento = solicitudDescuento, desctoid = descuento, tipodesctoid = tipoDescuento, fecha, alumno = alumnos, cantidad = curso, monto, validez, leadnum = leadId }, + commandType: System.Data.CommandType.StoredProcedure) ?? "ok"; + } + + public async Task PersonaPagarAsync(int cotizacionId) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.PagarCotizacion", + new { cotizacionid = cotizacionId }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + public async Task DesactivarAsync(int cotizacionId) + { + using var connection = new NpgsqlConnection(_connectionString); + await connection.ExecuteAsync( + "sige_sam_v3.DesactivarCotizacion", + new { cotizacionid = cotizacionId }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } +} diff --git a/backend/src/Ventas.Infrastructure/Repositories/InformeRepository.cs b/backend/src/Ventas.Infrastructure/Repositories/InformeRepository.cs new file mode 100644 index 0000000..36fb6ac --- /dev/null +++ b/backend/src/Ventas.Infrastructure/Repositories/InformeRepository.cs @@ -0,0 +1,85 @@ +using Dapper; +using Npgsql; +using Ventas.Core.Interfaces; + +namespace Ventas.Infrastructure.Repositories; + +public class InformeRepository : IInformeRepository +{ + private readonly string _connectionString; + + public InformeRepository(string connectionString) + { + _connectionString = connectionString; + } + + public async Task>> InformeMensualAsync(int mes, int agno, string tipo) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "sige_sam_v3.InformeVentasAgnoMes", + new { agno, mes, tipobusqueda = tipo }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> InformeMensualEjecutivoAsync(int mes, int agno, string tipo, string ejecutivo, int montoVenta) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "sige_sam_v3.InformeVentasAgnoMesEjecutivo", + new { agno, mes, tipobusqueda = tipo, ejecutivo = ejecutivo.ToUpper().Trim(), montovta = montoVenta }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> InformeLeadDiasAsync(DateTime inicio, DateTime termino, string vendedorId) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "Buscar_LeadDiarios", + new { inicio, termino, vendedor = vendedorId }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> InformeVentasCursosEmpresaAsync(string tipo, string varA, string varB, int varC) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "ModuloEmpresa_BusquedaVenta", + new { tipo, varz = varA, vary = varB, varx = varC }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> InformeDocumentosAsync(string tipo, string varA, string varB, int varC) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "ModuloEmpresa_BusquedaFinanzas", + new { tipo, varz = varA, vary = varB, varx = varC }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> InformeGeneralAsync(string busqueda, string varA, string varB) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "ModuloEmpresa_Informes", + new { tipo = busqueda, varz = varA, vary = varB }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + public async Task>> EjecutarCrystalSpAsync(string tipo, int prop, int cotz, int cont) + { + using var connection = new NpgsqlConnection(_connectionString); + var rows = await connection.QueryAsync( + "ModuloEmpresa_PropuestaCrystalReport", + new { tipo, prop, cotz, cont }, + commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } +} diff --git a/backend/src/Ventas.Infrastructure/Repositories/UsuarioRepository.cs b/backend/src/Ventas.Infrastructure/Repositories/UsuarioRepository.cs new file mode 100644 index 0000000..fd0855e --- /dev/null +++ b/backend/src/Ventas.Infrastructure/Repositories/UsuarioRepository.cs @@ -0,0 +1,45 @@ +using Dapper; +using Npgsql; +using Ventas.Core.Interfaces; + +namespace Ventas.Infrastructure.Repositories; + +public class UsuarioRepository : IUsuarioRepository +{ + private readonly string _connectionString; + + public UsuarioRepository(string connectionString) + { + _connectionString = connectionString; + } + + public async Task BuscarAsync(string usuario, string clave) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QueryAsync( + "sam.BuscarUsuario", + new { userid = usuario, passid = clave }, + commandType: System.Data.CommandType.StoredProcedure); + return result.Any() ? "ok" : ""; + } + + public async Task InfoAsync(string usuario) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QueryAsync( + "sige_sam_v3.BuscarUsuario", + new { usuarioid = usuario }, + commandType: System.Data.CommandType.StoredProcedure); + return result.Any() ? "ok" : ""; + } + + public async Task PerfilAsync(string usuario) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QueryAsync( + "sige_sam_v3.BuscarPerfilUsuario", + new { usuario }, + commandType: System.Data.CommandType.StoredProcedure); + return result.Any() ? "ok" : ""; + } +} diff --git a/backend/src/Ventas.Services/AlumnoService.cs b/backend/src/Ventas.Services/AlumnoService.cs index 76e122e..bd994a0 100644 --- a/backend/src/Ventas.Services/AlumnoService.cs +++ b/backend/src/Ventas.Services/AlumnoService.cs @@ -1,143 +1,63 @@ using Dapper; using Npgsql; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class AlumnoService { + private readonly IAlumnoRepository _alumnoRepository; private readonly string _connectionString; - public AlumnoService(string connectionString) + public AlumnoService(IAlumnoRepository alumnoRepository, string connectionString) { + _alumnoRepository = alumnoRepository; _connectionString = connectionString; } - public async Task>> BuscarAsync(string tipoBusqueda, string nombre) + private async Task>> QuerySpAsync(string sp, object parameters) { using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarAlumnos", - new { tipobusqueda = tipoBusqueda, nombrealumno = nombre }, - commandType: System.Data.CommandType.StoredProcedure); + var rows = await connection.QueryAsync(sp, parameters, commandType: System.Data.CommandType.StoredProcedure); return rows.Select(r => (Dictionary)(IDictionary)r!); } + public async Task>> BuscarAsync(string tipoBusqueda, string nombre) + => await QuerySpAsync("sige_sam_v3.BuscarAlumnos", new { tipobusqueda = tipoBusqueda, nombrealumno = nombre }); + public async Task IngresarV2Async(string rut, string nombre, string paterno, string materno, string fecha, string fono, string mail, int ocupacion, string profeOficio) - { - using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.IngresarAlumnosV2", - new { alumnorut = rut, alumnopaterno = paterno, alumnoMaterno = materno, alumnonombre = nombre, alumnodireccion = "SIN DIRECCION", comuna = "1", nacionalidad = 5, fecha, telefono = fono, email = mail, clave = rut, colegioid = 16285, profesionid = 23, ocupacionid = ocupacion, profesionoficio = profeOficio }, - commandType: System.Data.CommandType.StoredProcedure); - return "ok"; - } + => await _alumnoRepository.IngresarV2Async(rut, nombre, paterno, materno, "SIN DIRECCION", "1", fecha, fono, mail, ocupacion, profeOficio); public async Task IngresarApoderadoAsync(string rutApoderado, string rutAlumno, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fono, string mail) - { - using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.IngresarApoderado", - new { apoderado = rutApoderado, alumno = rutAlumno, paterno, materno, nombre, telefono = fono, mail, direccion, comuna, nacionalidad }, - commandType: System.Data.CommandType.StoredProcedure); - return "ok"; - } + => await _alumnoRepository.IngresarApoderadoAsync(rutApoderado, rutAlumno, nombre, paterno, materno, direccion, comuna, nacionalidad, fono, mail); public async Task>> BuscarApoderadoAsync(string tipoBusqueda, string nombre) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarApoderado", - new { tipobusqueda = tipoBusqueda, nombreapoderado = nombre }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarApoderado", new { tipobusqueda = tipoBusqueda, nombreapoderado = nombre }); public async Task>> OcupacionAsync() - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarOcupaciones", - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarOcupaciones", new { }); public async Task>> BuscarContratosAsync(string id) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sam.BuscarAlumnoContratoPersona", - new { alumnoid = id }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sam.BuscarAlumnoContratoPersona", new { alumnoid = id }); public async Task>> BuscarBloqueoAsync(string idAlumno) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarBloqueoFinazas", - new { idcliente = idAlumno }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarBloqueoFinazas", new { idcliente = idAlumno }); public async Task>> BuscarAntiguedadAsync(string idAlumno) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.AlumnoAntiguedad", - new { alumnoid = idAlumno }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.AlumnoAntiguedad", new { alumnoid = idAlumno }); public async Task>> BuscarFormasPagoAsync(int boleta) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.AlumnoFormaPagoContrato", - new { boleta }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.AlumnoFormaPagoContrato", new { boleta }); public async Task>> BuscarAnexosContratoAsync(string alumnoId, string contratoId) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.AlumnoBuscarAnexos", - new { alumnoid = alumnoId, contrato = contratoId }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.AlumnoBuscarAnexos", new { alumnoid = alumnoId, contrato = contratoId }); public async Task>> BuscarColegiosAsync(string nombre) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sam.BuscarColegios", - new { nombrelike = nombre }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sam.BuscarColegios", new { nombrelike = nombre }); public async Task>> BuscarProfesionesAsync(string nombre) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sam.BuscarProfesiones", - new { nombrelike = nombre }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sam.BuscarProfesiones", new { nombrelike = nombre }); public async Task>> BuscarComunasXnombreAsync(string nombre) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sam.BuscarComunasXnombre", - new { nombrelike = nombre }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sam.BuscarComunasXnombre", new { nombrelike = nombre }); } diff --git a/backend/src/Ventas.Services/ContratoService.cs b/backend/src/Ventas.Services/ContratoService.cs index f729446..0210b95 100644 --- a/backend/src/Ventas.Services/ContratoService.cs +++ b/backend/src/Ventas.Services/ContratoService.cs @@ -1,86 +1,47 @@ using Dapper; using Npgsql; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class ContratoService { + private readonly IContratoRepository _contratoRepository; private readonly string _connectionString; - public ContratoService(string connectionString) + public ContratoService(IContratoRepository contratoRepository, string connectionString) { + _contratoRepository = contratoRepository; _connectionString = connectionString; } - public async Task IngresarAsync(int cotizacionId, string fechaContrato, int boletaId, int vendedorId) + private async Task>> QuerySpAsync(string sp, object parameters) { using var connection = new NpgsqlConnection(_connectionString); - var result = await connection.QuerySingleOrDefaultAsync( - "sige_sam_v3.IngresarContrato", - new { cotizacion = cotizacionId, boletackt = 1, fecha = fechaContrato, boleta = boletaId, vendedor = vendedorId }, - commandType: System.Data.CommandType.StoredProcedure); - return result ?? "ok"; + var rows = await connection.QueryAsync(sp, parameters, commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); } + public async Task IngresarAsync(int cotizacionId, string fechaContrato, int boletaId, int vendedorId) + => await _contratoRepository.IngresarAsync(cotizacionId, 1, fechaContrato, boletaId, vendedorId); + public async Task IngresarDetalleAsync(int contratoId, string empresaId, string alumnoId, string cursoId, string fecha, int vendedor, int registroAcademico, int alumnoTipo) - { - using var connection = new NpgsqlConnection(_connectionString); - var result = await connection.QuerySingleOrDefaultAsync( - "sige_sam_v3.IngresarContratoDetalle", - new { contrato = contratoId, contratoempresa = empresaId, alumnoid = alumnoId, cursioid = cursoId, fecha, vendedorid = vendedor, tiporegistro = registroAcademico, tipoalumno = alumnoTipo }, - commandType: System.Data.CommandType.StoredProcedure); - return result ?? "ok"; - } + => await _contratoRepository.IngresarDetalleAsync(contratoId, empresaId, alumnoId, cursoId, fecha, vendedor, registroAcademico, alumnoTipo); public async Task>> PdfContratoAsync(int contrato) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.PDFContrato", - new { contrato }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.PDFContrato", new { contrato }); public async Task>> PdfContratoJornadasAsync(int contrato) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.PDFContratoJornadas", - new { contrato }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.PDFContratoJornadas", new { contrato }); public async Task>> PdfContratoProgramasCursosAsync(int contrato) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.PDFContratoProgramasCursos", - new { contrato }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.PDFContratoProgramasCursos", new { contrato }); public async Task>> PdfContratoSedesAsync(int contrato) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.PDFContratoSedes", - new { contrato }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.PDFContratoSedes", new { contrato }); public async Task>> BuscarInformacionAsync(int contrato) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarInfoContrato", - new { contratoid = contrato }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarInfoContrato", new { contratoid = contrato }); public async Task IngresarContratoEmpresaAsync(int cotizacionId, string empresaId, int tipoVenta, int facturaId, int cantCursos, int vendedorId) { @@ -105,30 +66,21 @@ public class ContratoService public async Task IngresarFirmaPendienteAsync(int contratoId) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "Empresa_IngresarContratoFirma", - new { cont = contratoId }, - commandType: System.Data.CommandType.StoredProcedure); + await connection.ExecuteAsync("Empresa_IngresarContratoFirma", new { cont = contratoId }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; } public async Task ActualizarEstadoContratoAsync(string tipo, int contId, string varA, int varB) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "Empresa_ActualizaContrato", - new { tipo, contrato = contId, varz = varA, vary = varB }, - commandType: System.Data.CommandType.StoredProcedure); + await connection.ExecuteAsync("Empresa_ActualizaContrato", new { tipo, contrato = contId, varz = varA, vary = varB }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; } public async Task ActualizarFirmaContratoAsync(string tipo, int contrato, int firmado) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "Empresa_ActualizaFirmaContrato", - new { tipoeleccion = tipo, cont = contrato, fir = firmado }, - commandType: System.Data.CommandType.StoredProcedure); + await connection.ExecuteAsync("Empresa_ActualizaFirmaContrato", new { tipoeleccion = tipo, cont = contrato, fir = firmado }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; } } diff --git a/backend/src/Ventas.Services/CotizacionService.cs b/backend/src/Ventas.Services/CotizacionService.cs index 964a255..061df4a 100644 --- a/backend/src/Ventas.Services/CotizacionService.cs +++ b/backend/src/Ventas.Services/CotizacionService.cs @@ -1,32 +1,34 @@ using Dapper; using Npgsql; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class CotizacionService { + private readonly ICotizacionRepository _cotizacionRepository; private readonly string _connectionString; - public CotizacionService(string connectionString) + public CotizacionService(ICotizacionRepository cotizacionRepository, string connectionString) { + _cotizacionRepository = cotizacionRepository; _connectionString = connectionString; } - public async Task IngresarAsync(string apoderadoId, string vendedorId, int descuento, int tipoDescuento, string fecha, int monto, string validez, int leadId) + private async Task>> QuerySpAsync(string sp, object parameters) { using var connection = new NpgsqlConnection(_connectionString); - var result = await connection.QuerySingleOrDefaultAsync( - "sige_sam_v3.IngresarCotizacionLead", - new { apoderado = apoderadoId, vendedor = vendedorId, solicituddescuento = 1, desctoid = descuento, tipodesctoid = tipoDescuento, fecha, alumno = 1, cantidad = 1, monto, validez, leadnum = leadId }, - commandType: System.Data.CommandType.StoredProcedure); - return result ?? "ok"; + var rows = await connection.QueryAsync(sp, parameters, commandType: System.Data.CommandType.StoredProcedure); + return rows.Select(r => (Dictionary)(IDictionary)r!); } + public async Task IngresarAsync(string apoderadoId, string vendedorId, int descuento, int tipoDescuento, string fecha, int monto, string validez, int leadId) + => await _cotizacionRepository.PersonaIngresarAsync(apoderadoId, vendedorId, 1, descuento, tipoDescuento, fecha, 1, 1, monto, validez, leadId); + public async Task IngresarDetalleAsync(int cotizacion, string alumnoId, int cursoId, int cantidad, int tarifa) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.IngresarCotizacionDetalle", + await connection.ExecuteAsync("sige_sam_v3.IngresarCotizacionDetalle", new { cotizaion = cotizacion, alumno = alumnoId, codigocurso = cursoId, cantidad, tarifa }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; @@ -35,72 +37,29 @@ public class CotizacionService public async Task DetalleSinCursoAsync(int cotizacion, string alumnoId, string apoderadoId, int programaId, int cantidad, int tarifa, int sedeId) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.IngresarAnexoCotiSinCurso", + await connection.ExecuteAsync("sige_sam_v3.IngresarAnexoCotiSinCurso", new { cotiid = cotizacion, alumnid = alumnoId, apoid = apoderadoId, programid = programaId, cursos = cantidad, tarifaid = tarifa, idsede = sedeId }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; } public async Task>> BuscarAsync(int lead) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarCotizacionLead", - new { leadid = lead }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarCotizacionLead", new { leadid = lead }); public async Task>> BuscarSinCursoAsync(int lead) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarCotizacionesSinCurso", - new { leadid = lead }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarCotizacionesSinCurso", new { leadid = lead }); public async Task>> BuscarInfoAsync(string tipoBusqueda, string nombre) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarCotizacion", - new { tipobusqueda = tipoBusqueda, nombre, fecha = DateTime.Now.ToString("yyyy-MM-dd") }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarCotizacion", new { tipobusqueda = tipoBusqueda, nombre, fecha = DateTime.Now.ToString("yyyy-MM-dd") }); public async Task>> DetalleAsync(int cotizacion) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.BuscarCotizacionDetalle", - new { cotizacion }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await QuerySpAsync("sige_sam_v3.BuscarCotizacionDetalle", new { cotizacion }); public async Task PersonaPagarAsync(int cotizacion) - { - using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.PagarCotizacion", - new { cotizacionid = cotizacion }, - commandType: System.Data.CommandType.StoredProcedure); - return "ok"; - } + => await _cotizacionRepository.PersonaPagarAsync(cotizacion); public async Task DesactivarAsync(int cotizacion) - { - using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "sige_sam_v3.DesactivarCotizacion", - new { cotizacionid = cotizacion }, - commandType: System.Data.CommandType.StoredProcedure); - return "ok"; - } + => await _cotizacionRepository.DesactivarAsync(cotizacion); public async Task CotizacionEmpIngresoAsync(string empresaId, string vendedor, int alumnos, int curso, int empresaMonto, int oticMonto, int alumnoMonto, int cotizacionTipo, DateTime validez, int descuentoId, int estadoId, string oticId, string motivo) { @@ -115,10 +74,7 @@ public class CotizacionService public async Task ActualizaEstadoCotizacionAsync(string tipo, int cotzId, string varA, int varB) { using var connection = new NpgsqlConnection(_connectionString); - await connection.ExecuteAsync( - "Empresa_ActualizaCotizacion", - new { tipo, cotizacion = cotzId, varz = varA, vary = varB }, - commandType: System.Data.CommandType.StoredProcedure); + await connection.ExecuteAsync("Empresa_ActualizaCotizacion", new { tipo, cotizacion = cotzId, varz = varA, vary = varB }, commandType: System.Data.CommandType.StoredProcedure); return "ok"; } } diff --git a/backend/src/Ventas.Services/EmpresaReportService.cs b/backend/src/Ventas.Services/EmpresaReportService.cs index 55820b8..78dd2c7 100644 --- a/backend/src/Ventas.Services/EmpresaReportService.cs +++ b/backend/src/Ventas.Services/EmpresaReportService.cs @@ -3,29 +3,22 @@ using Npgsql; using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class EmpresaReportService { + private readonly IInformeRepository _informeRepository; private readonly string _connectionString; - public EmpresaReportService(string connectionString) + public EmpresaReportService(IInformeRepository informeRepository, string connectionString) { + _informeRepository = informeRepository; _connectionString = connectionString; } - private async Task>> EjecutarCrystalSpAsync(string tipo, int prop, int cotz, int cont) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "ModuloEmpresa_PropuestaCrystalReport", - new { tipo, prop, cotz, cont }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } - - private async Task>> EjecutarContratoCrysAsync(string tipo, int cont) + private async Task>> ContratoCrysAsync(string tipo, int cont) { using var connection = new NpgsqlConnection(_connectionString); var rows = await connection.QueryAsync( @@ -40,10 +33,10 @@ public class EmpresaReportService public async Task ContratoAbiertoPdfAsync(int contratoId) { - var dt01 = await EjecutarContratoCrysAsync("CONTRATOREIMPRESION", contratoId); - var dt02 = await EjecutarContratoCrysAsync("DETALLECURSO", contratoId); - var dt03 = await EjecutarContratoCrysAsync("HORARIO", contratoId); - var dt04 = await EjecutarContratoCrysAsync("ALUMNO", contratoId); + var dt01 = await ContratoCrysAsync("CONTRATOREIMPRESION", contratoId); + var dt02 = await ContratoCrysAsync("DETALLECURSO", contratoId); + var dt03 = await ContratoCrysAsync("HORARIO", contratoId); + var dt04 = await ContratoCrysAsync("ALUMNO", contratoId); var header = dt01.FirstOrDefault(); if (header == null) return []; @@ -55,7 +48,6 @@ public class EmpresaReportService page.Size(PageSizes.A4); page.Margin(57); page.DefaultTextStyle(x => x.FontSize(9)); - page.Header().Element(c => ComposeEmpHeader(c, GetString(header, "NombreEmp"), contratoId.ToString())); page.Content().Element(c => ComposeEmpContent(c, header, dt02, dt03, dt04)); page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); }); @@ -65,11 +57,10 @@ public class EmpresaReportService public async Task ContratoCerradoPdfAsync(int propuestaId, int contratoId) { - var infoPropuesta = await EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, contratoId); - var infoCursos = await EjecutarCrystalSpAsync("CONTRATOCURSO", propuestaId, 0, contratoId); - var infoAlumnos = await EjecutarCrystalSpAsync("CONTRATOALUMNO", propuestaId, 0, contratoId); + var header = (await _informeRepository.EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, contratoId)).FirstOrDefault(); + var cursos = await _informeRepository.EjecutarCrystalSpAsync("CONTRATOCURSO", propuestaId, 0, contratoId); + var alumnos = await _informeRepository.EjecutarCrystalSpAsync("CONTRATOALUMNO", propuestaId, 0, contratoId); - var header = infoPropuesta.FirstOrDefault(); if (header == null) return []; return Document.Create(container => @@ -79,9 +70,8 @@ public class EmpresaReportService page.Size(PageSizes.A4); page.Margin(57); page.DefaultTextStyle(x => x.FontSize(9)); - page.Header().Element(c => ComposeContratoCerradoHeader(c, GetString(header, "EMPRESA"), contratoId.ToString())); - page.Content().Element(c => ComposeContratoCerradoContent(c, header, infoCursos, infoAlumnos)); + page.Content().Element(c => ComposeContratoCerradoContent(c, header, cursos, alumnos)); page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); }); }); }).GeneratePdf(); @@ -89,10 +79,9 @@ public class EmpresaReportService public async Task CotizacionCursoCerradoPdfAsync(int propuestaId) { - var data = await EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, 0); - var detalle = await EjecutarCrystalSpAsync("PROPUESTADET", propuestaId, 0, 0); + var header = (await _informeRepository.EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, 0)).FirstOrDefault(); + var detalle = await _informeRepository.EjecutarCrystalSpAsync("PROPUESTADET", propuestaId, 0, 0); - var header = data.FirstOrDefault(); if (header == null) return []; return Document.Create(container => @@ -102,7 +91,6 @@ public class EmpresaReportService page.Size(PageSizes.A4); page.Margin(57); page.DefaultTextStyle(x => x.FontSize(9)); - page.Header().Element(c => ComposeCotizacionCCHeader(c, GetString(header, "EMPRESA"), propuestaId.ToString())); page.Content().Element(c => ComposeCotizacionCCContent(c, header, detalle)); page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); }); @@ -112,10 +100,9 @@ public class EmpresaReportService public async Task CotizacionPlanCentralPdfAsync(int cotizacionId) { - var data = await EjecutarCrystalSpAsync("COTIZACIONV2", 0, cotizacionId, 0); - var detalle = await EjecutarCrystalSpAsync("COTIZACIONDETV2", 0, cotizacionId, 0); + var header = (await _informeRepository.EjecutarCrystalSpAsync("COTIZACIONV2", 0, cotizacionId, 0)).FirstOrDefault(); + var detalle = await _informeRepository.EjecutarCrystalSpAsync("COTIZACIONDETV2", 0, cotizacionId, 0); - var header = data.FirstOrDefault(); if (header == null) return []; return Document.Create(container => @@ -125,7 +112,6 @@ public class EmpresaReportService page.Size(PageSizes.A4); page.Margin(57); page.DefaultTextStyle(x => x.FontSize(9)); - page.Header().Element(c => ComposePlanCentralHeader(c, GetString(header, "Razon Social"), cotizacionId.ToString())); page.Content().Element(c => ComposePlanCentralContent(c, header, detalle)); page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); }); @@ -158,80 +144,43 @@ public class EmpresaReportService col.Item().PaddingTop(15).Table(table => { table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); }); - table.Cell().Text("Empresa:").Bold(); - table.Cell().Text(GetString(header, "NombreEmp")); - table.Cell().Text("RUT:").Bold(); - table.Cell().Text(GetString(header, "idEmpresa")); - table.Cell().Text("Dirección:").Bold(); - table.Cell().Text(GetString(header, "DireccionEmp")); - table.Cell().Text("Representante:").Bold(); - table.Cell().Text(GetString(header, "Representante")); - table.Cell().Text("Vendedor:").Bold(); - table.Cell().Text(GetString(header, "Vendedor")); + table.Cell().Text("Empresa:").Bold(); table.Cell().Text(GetString(header, "NombreEmp")); + table.Cell().Text("RUT:").Bold(); table.Cell().Text(GetString(header, "idEmpresa")); + table.Cell().Text("Dirección:").Bold(); table.Cell().Text(GetString(header, "DireccionEmp")); + table.Cell().Text("Representante:").Bold(); table.Cell().Text(GetString(header, "Representante")); + table.Cell().Text("Vendedor:").Bold(); table.Cell().Text(GetString(header, "Vendedor")); }); col.Item().PaddingTop(15).Table(table => { - table.ColumnsDefinition(c => - { - c.ConstantColumn(30); - c.RelativeColumn(); - c.ConstantColumn(60); - c.ConstantColumn(70); - c.ConstantColumn(70); - }); - - table.Header(h => - { - h.Cell().Text("#").Bold(); - h.Cell().Text("Curso").Bold(); - h.Cell().Text("Duración").Bold(); - h.Cell().Text("Inicio").Bold(); - h.Cell().Text("Término").Bold(); - }); - - int idx = 1; + table.ColumnsDefinition(c => { c.ConstantColumn(30); c.RelativeColumn(); c.ConstantColumn(60); c.ConstantColumn(70); c.ConstantColumn(70); }); + table.Header(h => { h.Cell().Text("#"); h.Cell().Text("Curso"); h.Cell().Text("Duración"); h.Cell().Text("Inicio"); h.Cell().Text("Término"); }); + int i = 1; foreach (var c in cursos) { - table.Cell().Text(idx++.ToString()); - table.Cell().Text(GetString(c, "Curso")); - table.Cell().Text(GetString(c, "Duracion")); - table.Cell().Text(GetString(c, "FechaInicio")); - table.Cell().Text(GetString(c, "FechaTermino")); + table.Cell().Text((i++).ToString()); table.Cell().Text(GetString(c, "Curso")); + table.Cell().Text(GetString(c, "Duracion")); table.Cell().Text(GetString(c, "FechaInicio")); table.Cell().Text(GetString(c, "FechaTermino")); } }); col.Item().PaddingTop(10).Text("Horarios:").Bold(); - foreach (var h in horarios) - { - col.Item().PaddingLeft(10).Text(GetString(h, "Horario")); - } + foreach (var h in horarios) col.Item().PaddingLeft(10).Text(GetString(h, "Horario")); col.Item().PaddingTop(10).Text("Alumnos:").Bold(); - foreach (var a in alumnos) - { - col.Item().PaddingLeft(10).Text(GetString(a, "Alumno")); - } + foreach (var a in alumnos) col.Item().PaddingLeft(10).Text(GetString(a, "Alumno")); }); } - private static void ComposeContratoCerradoHeader(IContainer container, string empresa, string numContrato) + private static void ComposeContratoCerradoHeader(IContainer container, string empresa, string num) { container.Row(row => { - row.RelativeItem().Column(col => - { - col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); - col.Item().Text("Módulo Empresa - Contrato Cerrado").FontSize(8); - }); - row.ConstantItem(140).AlignRight().Column(col => - { - col.Item().Text($"Contrato N° {numContrato}").FontSize(14).Bold(); - }); + row.RelativeItem().Column(col => { col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); col.Item().Text("Contrato Cerrado").FontSize(8); }); + row.ConstantItem(140).AlignRight().Column(col => { col.Item().Text($"Contrato N° {num}").FontSize(14).Bold(); }); }); } - private static void ComposeContratoCerradoContent(IContainer container, Dictionary header, + private static void ComposeContratoCerradoContent(IContainer container, Dictionary h, IEnumerable> cursos, IEnumerable> alumnos) { container.Column(col => @@ -239,84 +188,40 @@ public class EmpresaReportService col.Item().PaddingTop(15).Table(table => { table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); }); - table.Cell().Text("Empresa:").Bold(); - table.Cell().Text(GetString(header, "EMPRESA")); - table.Cell().Text("RUT:").Bold(); - table.Cell().Text(GetString(header, "RUT")); - table.Cell().Text("Dirección:").Bold(); - table.Cell().Text(GetString(header, "DIRECCION")); - table.Cell().Text("Vendedor:").Bold(); - table.Cell().Text(GetString(header, "VENDEDOR")); - table.Cell().Text("Total:").Bold(); - table.Cell().Text("$" + GetString(header, "TOTAL")); + table.Cell().Text("Empresa:").Bold(); table.Cell().Text(GetString(h, "EMPRESA")); + table.Cell().Text("RUT:").Bold(); table.Cell().Text(GetString(h, "RUT")); + table.Cell().Text("Vendedor:").Bold(); table.Cell().Text(GetString(h, "VENDEDOR")); + table.Cell().Text("Total:").Bold(); table.Cell().Text("$" + GetString(h, "TOTAL")); }); col.Item().PaddingTop(15).Table(table => { - table.ColumnsDefinition(c => - { - c.ConstantColumn(25); - c.RelativeColumn(); - c.ConstantColumn(50); - c.ConstantColumn(60); - c.ConstantColumn(60); - }); - - table.Header(h => - { - h.Cell().Text("#").Bold(); - h.Cell().Text("Curso").Bold(); - h.Cell().Text("Horas").Bold(); - h.Cell().Text("Inicio").Bold(); - h.Cell().Text("Valor").Bold(); - }); - - int idx = 1; + table.ColumnsDefinition(c => { c.ConstantColumn(25); c.RelativeColumn(); c.ConstantColumn(50); c.ConstantColumn(60); c.ConstantColumn(60); }); + table.Header(h => { h.Cell().Text("#"); h.Cell().Text("Curso"); h.Cell().Text("Horas"); h.Cell().Text("Inicio"); h.Cell().Text("Valor"); }); + int i = 1; foreach (var c in cursos) { - table.Cell().Text(idx++.ToString()); - table.Cell().Text(GetString(c, "CURSO")); - table.Cell().Text(GetString(c, "Duracion")); - table.Cell().Text(GetString(c, "FechaInicio")); - table.Cell().Text("$" + GetString(c, "ValorGrupal")); + table.Cell().Text((i++).ToString()); table.Cell().Text(GetString(c, "CURSO")); + table.Cell().Text(GetString(c, "Duracion")); table.Cell().Text(GetString(c, "FechaInicio")); table.Cell().Text("$" + GetString(c, "ValorGrupal")); } }); - col.Item().PaddingTop(15).Table(table => - { - table.ColumnsDefinition(c => { c.ConstantColumn(25); c.RelativeColumn(); }); - table.Header(h => - { - h.Cell().Text("#").Bold(); - h.Cell().Text("Alumno").Bold(); - }); - int idx = 1; - foreach (var a in alumnos) - { - table.Cell().Text(idx++.ToString()); - table.Cell().Text(GetString(a, "Alumnos")); - } - }); + col.Item().PaddingTop(10).Text("Alumnos:").Bold(); + int idx = 1; + foreach (var a in alumnos) col.Item().PaddingLeft(10).Text($"{idx++}. {GetString(a, "Alumnos")}"); }); } - private static void ComposeCotizacionCCHeader(IContainer container, string empresa, string numProp) + private static void ComposeCotizacionCCHeader(IContainer container, string empresa, string num) { container.Row(row => { - row.RelativeItem().Column(col => - { - col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); - col.Item().Text("Cotización Curso Cerrado").FontSize(8); - }); - row.ConstantItem(140).AlignRight().Column(col => - { - col.Item().Text($"Cotización N° {numProp}").FontSize(14).Bold(); - }); + row.RelativeItem().Column(col => { col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); col.Item().Text("Cotización Curso Cerrado").FontSize(8); }); + row.ConstantItem(140).AlignRight().Column(col => { col.Item().Text($"Cotización N° {num}").FontSize(14).Bold(); }); }); } - private static void ComposeCotizacionCCContent(IContainer container, Dictionary header, + private static void ComposeCotizacionCCContent(IContainer container, Dictionary h, IEnumerable> detalle) { container.Column(col => @@ -324,65 +229,37 @@ public class EmpresaReportService col.Item().PaddingTop(15).Table(table => { table.ColumnsDefinition(c => { c.ConstantColumn(100); c.RelativeColumn(); }); - table.Cell().Text("Empresa:").Bold(); - table.Cell().Text(GetString(header, "EMPRESA")); - table.Cell().Text("RUT:").Bold(); - table.Cell().Text(GetString(header, "RUT")); - table.Cell().Text("Vendedor:").Bold(); - table.Cell().Text(GetString(header, "VENDEDOR")); - table.Cell().Text("Total:").Bold(); - table.Cell().Text("$" + GetString(header, "TOTAL")); - table.Cell().Text("Vigencia:").Bold(); - table.Cell().Text(GetString(header, "VALIDEZ")); + table.Cell().Text("Empresa:").Bold(); table.Cell().Text(GetString(h, "EMPRESA")); + table.Cell().Text("RUT:").Bold(); table.Cell().Text(GetString(h, "RUT")); + table.Cell().Text("Vendedor:").Bold(); table.Cell().Text(GetString(h, "VENDEDOR")); + table.Cell().Text("Total:").Bold(); table.Cell().Text("$" + GetString(h, "TOTAL")); + table.Cell().Text("Vigencia:").Bold(); table.Cell().Text(GetString(h, "VALIDEZ")); }); col.Item().PaddingTop(15).Table(table => { - table.ColumnsDefinition(c => - { - c.ConstantColumn(25); - c.RelativeColumn(); - c.ConstantColumn(60); - c.ConstantColumn(60); - }); - - table.Header(h => - { - h.Cell().Text("#").Bold(); - h.Cell().Text("Curso").Bold(); - h.Cell().Text("Jornada").Bold(); - h.Cell().Text("Valor").Bold(); - }); - - int idx = 1; + table.ColumnsDefinition(c => { c.ConstantColumn(25); c.RelativeColumn(); c.ConstantColumn(60); c.ConstantColumn(60); }); + table.Header(h => { h.Cell().Text("#"); h.Cell().Text("Curso"); h.Cell().Text("Jornada"); h.Cell().Text("Valor"); }); + int i = 1; foreach (var d in detalle) { - table.Cell().Text(idx++.ToString()); - table.Cell().Text(GetString(d, "CURSO")); - table.Cell().Text(GetString(d, "JORNADA")); - table.Cell().Text("$" + GetString(d, "VALOR CURSO")); + table.Cell().Text((i++).ToString()); table.Cell().Text(GetString(d, "CURSO")); + table.Cell().Text(GetString(d, "JORNADA")); table.Cell().Text("$" + GetString(d, "VALOR CURSO")); } }); }); } - private static void ComposePlanCentralHeader(IContainer container, string empresa, string numCotizacion) + private static void ComposePlanCentralHeader(IContainer container, string empresa, string num) { container.Row(row => { - row.RelativeItem().Column(col => - { - col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); - col.Item().Text("Cotización Plan Central").FontSize(8); - }); - row.ConstantItem(140).AlignRight().Column(col => - { - col.Item().Text($"Cotización N° {numCotizacion}").FontSize(14).Bold(); - }); + row.RelativeItem().Column(col => { col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold(); col.Item().Text("Cotización Plan Central").FontSize(8); }); + row.ConstantItem(140).AlignRight().Column(col => { col.Item().Text($"Cotización N° {num}").FontSize(14).Bold(); }); }); } - private static void ComposePlanCentralContent(IContainer container, Dictionary header, + private static void ComposePlanCentralContent(IContainer container, Dictionary h, IEnumerable> detalle) { container.Column(col => @@ -390,46 +267,22 @@ public class EmpresaReportService col.Item().PaddingTop(15).Table(table => { table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); }); - table.Cell().Text("Empresa:").Bold(); - table.Cell().Text(GetString(header, "Razon Social")); - table.Cell().Text("RUT:").Bold(); - table.Cell().Text(GetString(header, "R.U.T.")); - table.Cell().Text("Ejecutivo:").Bold(); - table.Cell().Text(GetString(header, "Ejecutivo")); - table.Cell().Text("Total:").Bold(); - table.Cell().Text("$" + GetString(header, "Total con descuento")); - table.Cell().Text("Vigencia:").Bold(); - table.Cell().Text(GetString(header, "Vigencia")); + table.Cell().Text("Empresa:").Bold(); table.Cell().Text(GetString(h, "Razon Social")); + table.Cell().Text("RUT:").Bold(); table.Cell().Text(GetString(h, "R.U.T.")); + table.Cell().Text("Ejecutivo:").Bold(); table.Cell().Text(GetString(h, "Ejecutivo")); + table.Cell().Text("Total:").Bold(); table.Cell().Text("$" + GetString(h, "Total con descuento")); + table.Cell().Text("Vigencia:").Bold(); table.Cell().Text(GetString(h, "Vigencia")); }); col.Item().PaddingTop(15).Table(table => { - table.ColumnsDefinition(c => - { - c.ConstantColumn(25); - c.RelativeColumn(); - c.ConstantColumn(50); - c.ConstantColumn(60); - c.ConstantColumn(60); - }); - - table.Header(h => - { - h.Cell().Text("#").Bold(); - h.Cell().Text("Curso").Bold(); - h.Cell().Text("Periodo").Bold(); - h.Cell().Text("Inicio").Bold(); - h.Cell().Text("Valor").Bold(); - }); - - int idx = 1; + table.ColumnsDefinition(c => { c.ConstantColumn(25); c.RelativeColumn(); c.ConstantColumn(50); c.ConstantColumn(60); c.ConstantColumn(60); }); + table.Header(h => { h.Cell().Text("#"); h.Cell().Text("Curso"); h.Cell().Text("Periodo"); h.Cell().Text("Inicio"); h.Cell().Text("Valor"); }); + int i = 1; foreach (var d in detalle) { - table.Cell().Text(idx++.ToString()); - table.Cell().Text(GetString(d, "NombreCurso")); - table.Cell().Text(GetString(d, "Periodo")); - table.Cell().Text(GetString(d, "FechaInicio")); - table.Cell().Text("$" + GetString(d, "ValorCurso")); + table.Cell().Text((i++).ToString()); table.Cell().Text(GetString(d, "NombreCurso")); + table.Cell().Text(GetString(d, "Periodo")); table.Cell().Text(GetString(d, "FechaInicio")); table.Cell().Text("$" + GetString(d, "ValorCurso")); } }); }); diff --git a/backend/src/Ventas.Services/InformeService.cs b/backend/src/Ventas.Services/InformeService.cs index f8e2cd2..07876c3 100644 --- a/backend/src/Ventas.Services/InformeService.cs +++ b/backend/src/Ventas.Services/InformeService.cs @@ -1,74 +1,31 @@ -using Dapper; -using Npgsql; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class InformeService { - private readonly string _connectionString; + private readonly IInformeRepository _informeRepository; - public InformeService(string connectionString) + public InformeService(IInformeRepository informeRepository) { - _connectionString = connectionString; + _informeRepository = informeRepository; } public async Task>> InformeMensualAsync(int mes, int agno, string tipo) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.InformeVentasAgnoMes", - new { agno, mes, tipobusqueda = tipo }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeMensualAsync(mes, agno, tipo); public async Task>> InformeMensualEjecutivoAsync(int mes, int agno, string tipo, string ejecutivo, int montoVenta) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "sige_sam_v3.InformeVentasAgnoMesEjecutivo", - new { agno, mes, tipobusqueda = tipo, ejecutivo = ejecutivo.ToUpper().Trim(), montovta = montoVenta }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeMensualEjecutivoAsync(mes, agno, tipo, ejecutivo, montoVenta); public async Task>> InformeLeadDiasAsync(DateTime inicio, DateTime termino, string vendedorId) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "Buscar_LeadDiarios", - new { inicio, termino, vendedor = vendedorId }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeLeadDiasAsync(inicio, termino, vendedorId); public async Task>> InformeVentasCursosEmpresaAsync(string tipo, string varA, string varB, int varC) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "ModuloEmpresa_BusquedaVenta", - new { tipo, varz = varA, vary = varB, varx = varC }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeVentasCursosEmpresaAsync(tipo, varA, varB, varC); public async Task>> InformeDocumentosAsync(string tipo, string varA, string varB, int varC) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "ModuloEmpresa_BusquedaFinanzas", - new { tipo, varz = varA, vary = varB, varx = varC }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeDocumentosAsync(tipo, varA, varB, varC); public async Task>> InformeGeneralAsync(string busqueda, string varA, string varB) - { - using var connection = new NpgsqlConnection(_connectionString); - var rows = await connection.QueryAsync( - "ModuloEmpresa_Informes", - new { tipo = busqueda, varz = varA, vary = varB }, - commandType: System.Data.CommandType.StoredProcedure); - return rows.Select(r => (Dictionary)(IDictionary)r!); - } + => await _informeRepository.InformeGeneralAsync(busqueda, varA, varB); } diff --git a/backend/src/Ventas.Services/UsuarioService.cs b/backend/src/Ventas.Services/UsuarioService.cs index 5c126b8..9a22f5d 100644 --- a/backend/src/Ventas.Services/UsuarioService.cs +++ b/backend/src/Ventas.Services/UsuarioService.cs @@ -1,15 +1,18 @@ using Dapper; using Npgsql; using Ventas.Core.DTOs; +using Ventas.Core.Interfaces; namespace Ventas.Services; public class UsuarioService { + private readonly IUsuarioRepository _usuarioRepository; private readonly string _connectionString; - public UsuarioService(string connectionString) + public UsuarioService(IUsuarioRepository usuarioRepository, string connectionString) { + _usuarioRepository = usuarioRepository; _connectionString = connectionString; } @@ -22,8 +25,7 @@ public class UsuarioService commandType: System.Data.CommandType.StoredProcedure); var user = data.FirstOrDefault(); - if (user == null) - return null; + if (user == null) return null; var dict = (IDictionary)user; return new LoginResponse