From 2dfe7daa2cd3875dc4773d7ec12f72debb7c4858 Mon Sep 17 00:00:00 2001 From: Nurfog Date: Tue, 7 Jul 2026 17:59:38 -0400 Subject: [PATCH] feat: remaining services and controllers - ContratoService + ContratoController (CRUD, PDF data, empresa, firma) - CotizacionService + CotizacionController (CRUD, detalle, pago, empresa) - AlumnoService + AlumnoController (CRUD, apoderado, consultas, colegios) - InformeService + InformeController (reportes ventas, leads, documentos) - All services registered in DI (Program.cs) --- ROADMAP.md | 8 +- .../Controllers/AlumnoController.cs | 141 +++++++++++++++++ .../Controllers/ContratoController.cs | 85 +++++++++++ .../Controllers/CotizacionController.cs | 109 +++++++++++++ .../Controllers/InformeController.cs | 60 ++++++++ backend/src/Ventas.API/Program.cs | 8 + backend/src/Ventas.Services/AlumnoService.cs | 143 ++++++++++++++++++ .../src/Ventas.Services/ContratoService.cs | 134 ++++++++++++++++ .../src/Ventas.Services/CotizacionService.cs | 124 +++++++++++++++ backend/src/Ventas.Services/InformeService.cs | 74 +++++++++ 10 files changed, 884 insertions(+), 2 deletions(-) create mode 100644 backend/src/Ventas.API/Controllers/AlumnoController.cs create mode 100644 backend/src/Ventas.API/Controllers/ContratoController.cs create mode 100644 backend/src/Ventas.API/Controllers/CotizacionController.cs create mode 100644 backend/src/Ventas.API/Controllers/InformeController.cs create mode 100644 backend/src/Ventas.Services/AlumnoService.cs create mode 100644 backend/src/Ventas.Services/ContratoService.cs create mode 100644 backend/src/Ventas.Services/CotizacionService.cs create mode 100644 backend/src/Ventas.Services/InformeService.cs diff --git a/ROADMAP.md b/ROADMAP.md index ebd026a..eb1bf8e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -44,13 +44,16 @@ - [ ] SpComplexQueries.cs (Dapper multi-resultset) - [x] **1.4 Ventas.Services — Lógica de Negocio** (~2 sem) - [x] LeadService.cs, UsuarioService.cs, JwtService.cs - - [ ] Resto servicios (Contrato, Cotizacion, Alumno, etc.) + - [x] ContratoService.cs, CotizacionService.cs, AlumnoService.cs, InformeService.cs - [x] **1.5 Ventas.API — Controladores REST** (~1 sem) - [x] AuthController.cs (login + perfil) - [x] LeadController.cs (CRUD + actividades + pagos) + - [x] ContratoController.cs (CRUD + PDF + empresa + firma) + - [x] CotizacionController.cs (CRUD + detalle + pago + empresa) + - [x] AlumnoController.cs (CRUD + apoderado + consultas) + - [x] InformeController.cs (reportes ventas, leads, documentos) - [x] Program.cs completo (DI, JWT, CORS) - [x] appsettings.json con connection strings - - [ ] Resto controllers (Contrato, Cotizacion, Alumno, etc.) - [x] **1.6 Auth JWT** (~3 días) - [x] JwtService.cs (generación de tokens) - [x] Login endpoint funcional @@ -107,6 +110,7 @@ |-------|------|-------------|----------------| | 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 (Contrato, Cotizacion, Alumno, Informe) | Frontend setup | | | | | | | | | | | diff --git a/backend/src/Ventas.API/Controllers/AlumnoController.cs b/backend/src/Ventas.API/Controllers/AlumnoController.cs new file mode 100644 index 0000000..f3969e1 --- /dev/null +++ b/backend/src/Ventas.API/Controllers/AlumnoController.cs @@ -0,0 +1,141 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ventas.Services; + +namespace Ventas.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class AlumnoController : ControllerBase +{ + private readonly AlumnoService _alumnoService; + + public AlumnoController(AlumnoService alumnoService) + { + _alumnoService = alumnoService; + } + + [HttpGet] + public async Task Buscar([FromQuery] string tipoBusqueda, [FromQuery] string nombre) + { + var result = await _alumnoService.BuscarAsync(tipoBusqueda, nombre); + return Ok(result); + } + + [HttpPost] + public async Task Ingresar([FromBody] AlumnoIngresoRequest request) + { + var result = await _alumnoService.IngresarV2Async( + request.Rut, request.Nombre, request.Paterno, request.Materno, + request.Fecha, request.Fono, request.Mail, request.Ocupacion, request.ProfesionOficio); + return Ok(new { mensaje = result }); + } + + [HttpPost("apoderado")] + public async Task IngresarApoderado([FromBody] ApoderadoIngresoRequest request) + { + var result = await _alumnoService.IngresarApoderadoAsync( + request.RutApoderado, request.RutAlumno, request.Nombre, request.Paterno, + request.Materno, request.Direccion, request.Comuna, request.Nacionalidad, + request.Fono, request.Mail); + return Ok(new { mensaje = result }); + } + + [HttpGet("apoderado")] + public async Task BuscarApoderado([FromQuery] string tipoBusqueda, [FromQuery] string nombre) + { + var result = await _alumnoService.BuscarApoderadoAsync(tipoBusqueda, nombre); + return Ok(result); + } + + [HttpGet("ocupaciones")] + public async Task Ocupaciones() + { + var result = await _alumnoService.OcupacionAsync(); + return Ok(result); + } + + [HttpGet("{id}/contratos")] + public async Task BuscarContratos(string id) + { + var result = await _alumnoService.BuscarContratosAsync(id); + return Ok(result); + } + + [HttpGet("{id}/bloqueo")] + public async Task Bloqueo(string id) + { + var result = await _alumnoService.BuscarBloqueoAsync(id); + return Ok(result); + } + + [HttpGet("{id}/antiguedad")] + public async Task Antiguedad(string id) + { + var result = await _alumnoService.BuscarAntiguedadAsync(id); + return Ok(result); + } + + [HttpGet("{id}/formas-pago")] + public async Task FormasPago(string id, [FromQuery] int boleta) + { + var result = await _alumnoService.BuscarFormasPagoAsync(boleta); + return Ok(result); + } + + [HttpGet("{id}/anexos")] + public async Task AnexosContrato(string id, [FromQuery] string contratoId) + { + var result = await _alumnoService.BuscarAnexosContratoAsync(id, contratoId); + return Ok(result); + } + + [HttpGet("colegios")] + public async Task BuscarColegios([FromQuery] string nombre) + { + var result = await _alumnoService.BuscarColegiosAsync(nombre); + return Ok(result); + } + + [HttpGet("profesiones")] + public async Task BuscarProfesiones([FromQuery] string nombre) + { + var result = await _alumnoService.BuscarProfesionesAsync(nombre); + return Ok(result); + } + + [HttpGet("comunas")] + public async Task BuscarComunas([FromQuery] string nombre) + { + var result = await _alumnoService.BuscarComunasXnombreAsync(nombre); + return Ok(result); + } +} + +public class AlumnoIngresoRequest +{ + public string Rut { get; set; } = string.Empty; + public string Nombre { get; set; } = string.Empty; + public string Paterno { get; set; } = string.Empty; + public string Materno { get; set; } = string.Empty; + public string Fecha { get; set; } = string.Empty; + public string Fono { get; set; } = string.Empty; + public string Mail { get; set; } = string.Empty; + public int Ocupacion { get; set; } + public string ProfesionOficio { get; set; } = string.Empty; +} + +public class ApoderadoIngresoRequest +{ + public string RutApoderado { get; set; } = string.Empty; + public string RutAlumno { get; set; } = string.Empty; + public string Nombre { get; set; } = string.Empty; + public string Paterno { get; set; } = string.Empty; + public string Materno { get; set; } = string.Empty; + public string Direccion { get; set; } = string.Empty; + public string Comuna { get; set; } = string.Empty; + public int Nacionalidad { get; set; } + public string Fono { get; set; } = string.Empty; + public string Mail { get; set; } = string.Empty; +} diff --git a/backend/src/Ventas.API/Controllers/ContratoController.cs b/backend/src/Ventas.API/Controllers/ContratoController.cs new file mode 100644 index 0000000..c70576d --- /dev/null +++ b/backend/src/Ventas.API/Controllers/ContratoController.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ventas.Services; + +namespace Ventas.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class ContratoController : ControllerBase +{ + private readonly ContratoService _contratoService; + + public ContratoController(ContratoService contratoService) + { + _contratoService = contratoService; + } + + [HttpPost] + public async Task Ingresar([FromQuery] int cotizacionId, [FromQuery] string fechaContrato, [FromQuery] int boletaId, [FromQuery] int vendedorId) + { + var result = await _contratoService.IngresarAsync(cotizacionId, fechaContrato, boletaId, vendedorId); + return Ok(new { id = result }); + } + + [HttpPost("detalle")] + public async Task IngresarDetalle([FromQuery] int contratoId, [FromQuery] string empresaId, [FromQuery] string alumnoId, [FromQuery] string cursoId, [FromQuery] string fecha, [FromQuery] int vendedor, [FromQuery] int registroAcademico, [FromQuery] int alumnoTipo) + { + var result = await _contratoService.IngresarDetalleAsync(contratoId, empresaId, alumnoId, cursoId, fecha, vendedor, registroAcademico, alumnoTipo); + return Ok(new { id = result }); + } + + [HttpGet("{id}/pdf")] + public async Task PdfContrato(int id) + { + var data = await _contratoService.PdfContratoAsync(id); + var jornadas = await _contratoService.PdfContratoJornadasAsync(id); + var programas = await _contratoService.PdfContratoProgramasCursosAsync(id); + var sedes = await _contratoService.PdfContratoSedesAsync(id); + + return Ok(new { data, jornadas, programas, sedes }); + } + + [HttpGet("{id}")] + public async Task BuscarInformacion(int id) + { + var result = await _contratoService.BuscarInformacionAsync(id); + return Ok(result); + } + + [HttpPost("empresa")] + public async Task IngresarContratoEmpresa([FromQuery] int cotizacionId, [FromQuery] string empresaId, [FromQuery] int tipoVenta, [FromQuery] int facturaId, [FromQuery] int cantCursos, [FromQuery] int vendedorId) + { + var result = await _contratoService.IngresarContratoEmpresaAsync(cotizacionId, empresaId, tipoVenta, facturaId, cantCursos, vendedorId); + return Ok(new { id = result }); + } + + [HttpPost("cerrado")] + public async Task IngresarContratoCerrado([FromQuery] int prop, [FromQuery] string rut, [FromQuery] int tipoVenta, [FromQuery] string vendedorId) + { + var result = await _contratoService.IngresarContratoCerradoAsync(prop, rut, tipoVenta, vendedorId); + return Ok(new { id = result }); + } + + [HttpPost("{id}/firma")] + public async Task IngresarFirmaPendiente(int id) + { + var result = await _contratoService.IngresarFirmaPendienteAsync(id); + return Ok(new { mensaje = result }); + } + + [HttpPut("{id}/estado")] + public async Task ActualizarEstado(int id, [FromQuery] string tipo, [FromQuery] string varA, [FromQuery] int varB) + { + var result = await _contratoService.ActualizarEstadoContratoAsync(tipo, id, varA, varB); + return Ok(new { mensaje = result }); + } + + [HttpPut("{id}/firma")] + public async Task ActualizarFirma(int id, [FromQuery] string tipo, [FromQuery] int firmado) + { + var result = await _contratoService.ActualizarFirmaContratoAsync(tipo, id, firmado); + return Ok(new { mensaje = result }); + } +} diff --git a/backend/src/Ventas.API/Controllers/CotizacionController.cs b/backend/src/Ventas.API/Controllers/CotizacionController.cs new file mode 100644 index 0000000..7b5b3f9 --- /dev/null +++ b/backend/src/Ventas.API/Controllers/CotizacionController.cs @@ -0,0 +1,109 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ventas.Services; + +namespace Ventas.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class CotizacionController : ControllerBase +{ + private readonly CotizacionService _cotizacionService; + + public CotizacionController(CotizacionService cotizacionService) + { + _cotizacionService = cotizacionService; + } + + [HttpPost] + public async Task Ingresar([FromQuery] string apoderadoId, [FromQuery] string vendedorId, [FromQuery] int descuento, [FromQuery] int tipoDescuento, [FromQuery] string fecha, [FromQuery] int monto, [FromQuery] string validez, [FromQuery] int leadId) + { + var result = await _cotizacionService.IngresarAsync(apoderadoId, vendedorId, descuento, tipoDescuento, fecha, monto, validez, leadId); + return Ok(new { id = result }); + } + + [HttpPost("detalle")] + public async Task IngresarDetalle([FromQuery] int cotizacion, [FromQuery] string alumnoId, [FromQuery] int cursoId, [FromQuery] int cantidad, [FromQuery] int tarifa) + { + var result = await _cotizacionService.IngresarDetalleAsync(cotizacion, alumnoId, cursoId, cantidad, tarifa); + return Ok(new { mensaje = result }); + } + + [HttpPost("detalle-sin-curso")] + public async Task DetalleSinCurso([FromQuery] int cotizacion, [FromQuery] string alumnoId, [FromQuery] string apoderadoId, [FromQuery] int programaId, [FromQuery] int cantidad, [FromQuery] int tarifa, [FromQuery] int sedeId) + { + var result = await _cotizacionService.DetalleSinCursoAsync(cotizacion, alumnoId, apoderadoId, programaId, cantidad, tarifa, sedeId); + return Ok(new { mensaje = result }); + } + + [HttpGet("lead/{lead}")] + public async Task BuscarPorLead(int lead) + { + var result = await _cotizacionService.BuscarAsync(lead); + return Ok(result); + } + + [HttpGet("lead/{lead}/sin-curso")] + public async Task BuscarSinCurso(int lead) + { + var result = await _cotizacionService.BuscarSinCursoAsync(lead); + return Ok(result); + } + + [HttpGet("buscar")] + public async Task BuscarInfo([FromQuery] string tipoBusqueda, [FromQuery] string nombre) + { + var result = await _cotizacionService.BuscarInfoAsync(tipoBusqueda, nombre); + return Ok(result); + } + + [HttpGet("{id}/detalle")] + public async Task Detalle(int id) + { + var result = await _cotizacionService.DetalleAsync(id); + return Ok(result); + } + + [HttpPost("{id}/pagar")] + public async Task Pagar(int id) + { + var result = await _cotizacionService.PersonaPagarAsync(id); + return Ok(new { mensaje = result }); + } + + [HttpPut("{id}/desactivar")] + public async Task Desactivar(int id) + { + var result = await _cotizacionService.DesactivarAsync(id); + return Ok(new { mensaje = result }); + } + + [HttpPost("empresa")] + public async Task CotizacionEmpIngreso([FromBody] CotizacionEmpRequest request) + { + var result = await _cotizacionService.CotizacionEmpIngresoAsync( + request.EmpresaId, request.Vendedor, request.Alumnos, request.Curso, + request.EmpresaMonto, request.OticMonto, request.AlumnoMonto, + request.CotizacionTipo, request.Validez, request.DescuentoId, + request.EstadoId, request.OticId, request.Motivo); + return Ok(new { id = result }); + } +} + +public class CotizacionEmpRequest +{ + public string EmpresaId { get; set; } = string.Empty; + public string Vendedor { get; set; } = string.Empty; + public int Alumnos { get; set; } + public int Curso { get; set; } + public int EmpresaMonto { get; set; } + public int OticMonto { get; set; } + public int AlumnoMonto { get; set; } + public int CotizacionTipo { get; set; } + public DateTime Validez { get; set; } + public int DescuentoId { get; set; } + public int EstadoId { get; set; } + public string OticId { get; set; } = string.Empty; + public string Motivo { get; set; } = string.Empty; +} diff --git a/backend/src/Ventas.API/Controllers/InformeController.cs b/backend/src/Ventas.API/Controllers/InformeController.cs new file mode 100644 index 0000000..b9fb9d3 --- /dev/null +++ b/backend/src/Ventas.API/Controllers/InformeController.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ventas.Services; + +namespace Ventas.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class InformeController : ControllerBase +{ + private readonly InformeService _informeService; + + public InformeController(InformeService informeService) + { + _informeService = informeService; + } + + [HttpGet("ventas-mensuales")] + public async Task InformeMensual([FromQuery] int mes, [FromQuery] int agno, [FromQuery] string tipo) + { + var result = await _informeService.InformeMensualAsync(mes, agno, tipo); + return Ok(result); + } + + [HttpGet("ventas-ejecutivo")] + public async Task InformeEjecutivo([FromQuery] int mes, [FromQuery] int agno, [FromQuery] string tipo, [FromQuery] string ejecutivo, [FromQuery] int montoVenta) + { + var result = await _informeService.InformeMensualEjecutivoAsync(mes, agno, tipo, ejecutivo, montoVenta); + return Ok(result); + } + + [HttpGet("lead-diarios")] + public async Task InformeLeadDias([FromQuery] DateTime inicio, [FromQuery] DateTime termino, [FromQuery] string vendedorId) + { + var result = await _informeService.InformeLeadDiasAsync(inicio, termino, vendedorId); + return Ok(result); + } + + [HttpGet("ventas-empresa")] + public async Task VentasCursosEmpresa([FromQuery] string tipo, [FromQuery] string varA, [FromQuery] string varB, [FromQuery] int varC) + { + var result = await _informeService.InformeVentasCursosEmpresaAsync(tipo, varA, varB, varC); + return Ok(result); + } + + [HttpGet("documentos")] + public async Task InformeDocumentos([FromQuery] string tipo, [FromQuery] string varA, [FromQuery] string varB, [FromQuery] int varC) + { + var result = await _informeService.InformeDocumentosAsync(tipo, varA, varB, varC); + return Ok(result); + } + + [HttpGet("general")] + public async Task InformeGeneral([FromQuery] string busqueda, [FromQuery] string varA, [FromQuery] string varB) + { + var result = await _informeService.InformeGeneralAsync(busqueda, varA, varB); + return Ok(result); + } +} diff --git a/backend/src/Ventas.API/Program.cs b/backend/src/Ventas.API/Program.cs index 65a262e..c828976 100644 --- a/backend/src/Ventas.API/Program.cs +++ b/backend/src/Ventas.API/Program.cs @@ -26,6 +26,14 @@ builder.Services.AddScoped(sp => new LeadService(connectionString)); builder.Services.AddScoped(sp => new UsuarioService(connectionString)); +builder.Services.AddScoped(sp => + new ContratoService(connectionString)); +builder.Services.AddScoped(sp => + new CotizacionService(connectionString)); +builder.Services.AddScoped(sp => + new AlumnoService(connectionString)); +builder.Services.AddScoped(sp => + new InformeService(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.Services/AlumnoService.cs b/backend/src/Ventas.Services/AlumnoService.cs new file mode 100644 index 0000000..76e122e --- /dev/null +++ b/backend/src/Ventas.Services/AlumnoService.cs @@ -0,0 +1,143 @@ +using Dapper; +using Npgsql; + +namespace Ventas.Services; + +public class AlumnoService +{ + private readonly string _connectionString; + + public AlumnoService(string connectionString) + { + _connectionString = connectionString; + } + + public async Task>> BuscarAsync(string tipoBusqueda, string nombre) + { + 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); + return rows.Select(r => (Dictionary)(IDictionary)r!); + } + + 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"; + } + + 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>> 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } +} diff --git a/backend/src/Ventas.Services/ContratoService.cs b/backend/src/Ventas.Services/ContratoService.cs new file mode 100644 index 0000000..f729446 --- /dev/null +++ b/backend/src/Ventas.Services/ContratoService.cs @@ -0,0 +1,134 @@ +using Dapper; +using Npgsql; + +namespace Ventas.Services; + +public class ContratoService +{ + private readonly string _connectionString; + + public ContratoService(string connectionString) + { + _connectionString = connectionString; + } + + public async Task IngresarAsync(int cotizacionId, string fechaContrato, int boletaId, int vendedorId) + { + 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"; + } + + 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"; + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + public async Task IngresarContratoEmpresaAsync(int cotizacionId, string empresaId, int tipoVenta, int facturaId, int cantCursos, int vendedorId) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QuerySingleOrDefaultAsync( + "IngresarContratoEmpresa", + new { cotizacionid = cotizacionId, empresaid = empresaId, tipoventaid = tipoVenta, facturaid = facturaId, cantidadcursos = cantCursos, vendedorid = vendedorId }, + commandType: System.Data.CommandType.StoredProcedure); + return result ?? "ok"; + } + + public async Task IngresarContratoCerradoAsync(int prop, string rut, int tipoVenta, string vendedorId) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QuerySingleOrDefaultAsync( + "Empresa_IngresarContratoV2", + new { prop, rut, tipo = tipoVenta, vendedor = vendedorId }, + commandType: System.Data.CommandType.StoredProcedure); + return result ?? "ok"; + } + + 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); + 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); + 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); + return "ok"; + } +} diff --git a/backend/src/Ventas.Services/CotizacionService.cs b/backend/src/Ventas.Services/CotizacionService.cs new file mode 100644 index 0000000..964a255 --- /dev/null +++ b/backend/src/Ventas.Services/CotizacionService.cs @@ -0,0 +1,124 @@ +using Dapper; +using Npgsql; + +namespace Ventas.Services; + +public class CotizacionService +{ + private readonly string _connectionString; + + public CotizacionService(string connectionString) + { + _connectionString = connectionString; + } + + public async Task IngresarAsync(string apoderadoId, string vendedorId, int descuento, int tipoDescuento, string fecha, int monto, string validez, int leadId) + { + 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"; + } + + 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", + new { cotizaion = cotizacion, alumno = alumnoId, codigocurso = cursoId, cantidad, tarifa }, + commandType: System.Data.CommandType.StoredProcedure); + return "ok"; + } + + 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", + 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!); + } + + 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!); + } + + 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!); + } + + 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!); + } + + 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"; + } + + 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"; + } + + 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) + { + using var connection = new NpgsqlConnection(_connectionString); + var result = await connection.QuerySingleOrDefaultAsync( + "Empresa_IngresarCotizacionEmpresaV2", + new { rutempresa = empresaId, vendedor, cantidadcursos = curso, cantidadalumnos = alumnos, montpempresa = empresaMonto, montootic = oticMonto, montoalm = alumnoMonto, tipocotz = cotizacionTipo, validez, iddescuento = descuentoId, idestado = estadoId, oticid = oticId, motivo }, + commandType: System.Data.CommandType.StoredProcedure); + return result ?? "ok"; + } + + 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); + return "ok"; + } +} diff --git a/backend/src/Ventas.Services/InformeService.cs b/backend/src/Ventas.Services/InformeService.cs new file mode 100644 index 0000000..f8e2cd2 --- /dev/null +++ b/backend/src/Ventas.Services/InformeService.cs @@ -0,0 +1,74 @@ +using Dapper; +using Npgsql; + +namespace Ventas.Services; + +public class InformeService +{ + private readonly string _connectionString; + + public InformeService(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!); + } +}