feat: services, jwt auth, and api controllers
- LeadService with 15 SP calls (CRUD, actividades, pagos, montos) - UsuarioService for login and profile queries - JwtService for token generation with claims - AuthController (login, perfil) with HttpOnly cookie - LeadController (CRUD, actividades, estado, pago, contacto) - Registered all services in DI (Program.cs)
This commit is contained in:
+18
-15
@@ -14,9 +14,9 @@
|
|||||||
| Backend .NET 10 — Skeleton (sln + 4 proyectos + NuGet) | ✅ CREADO |
|
| Backend .NET 10 — Skeleton (sln + 4 proyectos + NuGet) | ✅ CREADO |
|
||||||
| Entidades / DTOs / Interfaces (Ventas.Core) | ✅ CREADO |
|
| Entidades / DTOs / Interfaces (Ventas.Core) | ✅ CREADO |
|
||||||
| Infrastructure (EF Core + Dapper + Repos) | ✅ PARCIAL (DbContext + LeadRepository listos) |
|
| Infrastructure (EF Core + Dapper + Repos) | ✅ PARCIAL (DbContext + LeadRepository listos) |
|
||||||
| Services (lógica de negocio) | ❌ PENDIENTE |
|
| Services (lógica de negocio) | ✅ PARCIAL (LeadService, UsuarioService, JwtService) |
|
||||||
| API Controllers | ❌ PENDIENTE |
|
| API Controllers | ✅ PARCIAL (AuthController, LeadController) |
|
||||||
| Auth JWT | ❌ PENDIENTE |
|
| Auth JWT | ✅ CREADO (JwtService + middleware) |
|
||||||
| Reportes QuestPDF (17 reportes) | ❌ PENDIENTE |
|
| Reportes QuestPDF (17 reportes) | ❌ PENDIENTE |
|
||||||
| ServicesExternos.API | ❌ PENDIENTE |
|
| ServicesExternos.API | ❌ PENDIENTE |
|
||||||
| Frontend Next.js | ❌ PENDIENTE |
|
| Frontend Next.js | ❌ PENDIENTE |
|
||||||
@@ -42,17 +42,19 @@
|
|||||||
- [ ] Configurations/ (EF mapping)
|
- [ ] Configurations/ (EF mapping)
|
||||||
- [ ] Resto repos (Alumno, Contrato, Cotizacion, etc.)
|
- [ ] Resto repos (Alumno, Contrato, Cotizacion, etc.)
|
||||||
- [ ] SpComplexQueries.cs (Dapper multi-resultset)
|
- [ ] SpComplexQueries.cs (Dapper multi-resultset)
|
||||||
- [ ] **1.4 Ventas.Services — Lógica de Negocio** (~2 sem)
|
- [x] **1.4 Ventas.Services — Lógica de Negocio** (~2 sem)
|
||||||
- [ ] LeadService.cs + resto servicios (~15)
|
- [x] LeadService.cs, UsuarioService.cs, JwtService.cs
|
||||||
- [ ] **1.5 Ventas.API — Controladores REST** (~1 sem)
|
- [ ] Resto servicios (Contrato, Cotizacion, Alumno, etc.)
|
||||||
- [ ] AuthController.cs
|
- [x] **1.5 Ventas.API — Controladores REST** (~1 sem)
|
||||||
- [ ] LeadController.cs + resto controllers (~20)
|
- [x] AuthController.cs (login + perfil)
|
||||||
- [ ] Program.cs completo (DI, JWT, CORS)
|
- [x] LeadController.cs (CRUD + actividades + pagos)
|
||||||
- [ ] appsettings.json con connection strings
|
- [x] Program.cs completo (DI, JWT, CORS)
|
||||||
- [ ] **1.6 Auth JWT** (~3 días)
|
- [x] appsettings.json con connection strings
|
||||||
- [ ] JwtMiddleware.cs
|
- [ ] Resto controllers (Contrato, Cotizacion, Alumno, etc.)
|
||||||
- [ ] Login endpoint funcional
|
- [x] **1.6 Auth JWT** (~3 días)
|
||||||
- [ ] Claims → cookies HttpOnly
|
- [x] JwtService.cs (generación de tokens)
|
||||||
|
- [x] Login endpoint funcional
|
||||||
|
- [x] Claims → cookies HttpOnly
|
||||||
- [ ] **1.7 Reportes QuestPDF** (~2-3 sem)
|
- [ ] **1.7 Reportes QuestPDF** (~2-3 sem)
|
||||||
- [ ] ReportService.cs (base)
|
- [ ] ReportService.cs (base)
|
||||||
- [ ] 17 reportes (Contrato, Cotización, Arqueo, etc.)
|
- [ ] 17 reportes (Contrato, Cotización, Arqueo, etc.)
|
||||||
@@ -103,7 +105,8 @@
|
|||||||
|
|
||||||
| Fecha | Fase | Qué se hizo | Siguiente paso |
|
| Fecha | Fase | Qué se hizo | Siguiente paso |
|
||||||
|-------|------|-------------|----------------|
|
|-------|------|-------------|----------------|
|
||||||
| 2026-07-07 | F1 | Entities (25), Enums (4), DTOs, Interfaces (6), DbContext, LeadRepository, LeadQueryRepository, DI setup, appsettings | Resto repos (Contrato, Cotizacion, Alumno) + Controllers |
|
| 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 |
|
||||||
| | | | |
|
| | | | |
|
||||||
| | | | |
|
| | | | |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ventas.Core.DTOs;
|
||||||
|
using Ventas.Services;
|
||||||
|
|
||||||
|
namespace Ventas.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class AuthController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly UsuarioService _usuarioService;
|
||||||
|
private readonly JwtService _jwtService;
|
||||||
|
|
||||||
|
public AuthController(UsuarioService usuarioService, JwtService jwtService)
|
||||||
|
{
|
||||||
|
_usuarioService = usuarioService;
|
||||||
|
_jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("login")]
|
||||||
|
public async Task<IActionResult> Login([FromBody] LoginRequest request)
|
||||||
|
{
|
||||||
|
var usuario = await _usuarioService.LoginAsync(request);
|
||||||
|
if (usuario == null)
|
||||||
|
return Unauthorized(new { mensaje = "Credenciales inválidas" });
|
||||||
|
|
||||||
|
var token = _jwtService.GenerateToken(request.Rut, usuario.Nombre, usuario.Sede ?? "");
|
||||||
|
|
||||||
|
Response.Cookies.Append("SAM_TOKEN", token, new CookieOptions
|
||||||
|
{
|
||||||
|
HttpOnly = true,
|
||||||
|
Secure = true,
|
||||||
|
SameSite = SameSiteMode.Strict,
|
||||||
|
Expires = DateTime.UtcNow.AddMinutes(30)
|
||||||
|
});
|
||||||
|
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
nombre = usuario.Nombre,
|
||||||
|
sede = usuario.Sede,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("perfil")]
|
||||||
|
public async Task<IActionResult> Perfil([FromQuery] string usuarioId)
|
||||||
|
{
|
||||||
|
var perfil = await _usuarioService.PerfilAsync(usuarioId);
|
||||||
|
if (perfil == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
return Ok(perfil);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ventas.Core.DTOs;
|
||||||
|
using Ventas.Services;
|
||||||
|
|
||||||
|
namespace Ventas.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class LeadController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly LeadService _leadService;
|
||||||
|
|
||||||
|
public LeadController(LeadService leadService)
|
||||||
|
{
|
||||||
|
_leadService = leadService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<IActionResult> GetById(int id)
|
||||||
|
{
|
||||||
|
var result = await _leadService.BuscarIDAsync(id);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("buscar")]
|
||||||
|
public async Task<IActionResult> Buscar([FromQuery] int ejecutivo, [FromQuery] int estado, [FromQuery] int dias)
|
||||||
|
{
|
||||||
|
var result = await _leadService.BuscarAsync(ejecutivo, estado, dias);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("nuevos")]
|
||||||
|
public async Task<IActionResult> Nuevos([FromQuery] int ejecutivo)
|
||||||
|
{
|
||||||
|
var result = await _leadService.BuscarNuevosAsync(ejecutivo);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}/actividades")]
|
||||||
|
public async Task<IActionResult> Actividades(int id, [FromQuery] string tipo)
|
||||||
|
{
|
||||||
|
var result = await _leadService.ActividadesAsync(id, tipo);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("montos")]
|
||||||
|
public async Task<IActionResult> Montos([FromQuery] int ejecutivo)
|
||||||
|
{
|
||||||
|
var result = await _leadService.MontosAsync(ejecutivo);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("motivos-perdido")]
|
||||||
|
public async Task<IActionResult> MotivosPerdido()
|
||||||
|
{
|
||||||
|
var result = await _leadService.MotivosPerdidoAsync();
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Ingresar([FromBody] LeadCreateDto dto)
|
||||||
|
{
|
||||||
|
var result = await _leadService.IngresarAsync(dto);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id}/actividad")]
|
||||||
|
public async Task<IActionResult> IngresarActividad(int id, [FromBody] ActividadCreateDto dto, [FromQuery] string usuarioId)
|
||||||
|
{
|
||||||
|
var result = await _leadService.IngresarActividadAsync(id, dto.Tipo, dto.Descripcion, usuarioId);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}/estado")]
|
||||||
|
public async Task<IActionResult> ActualizarEstado(int id, [FromQuery] int estadoId)
|
||||||
|
{
|
||||||
|
var result = await _leadService.EstadoUpdateAsync(id, estadoId);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}/producto")]
|
||||||
|
public async Task<IActionResult> ActualizarProducto(int id, [FromQuery] string producto)
|
||||||
|
{
|
||||||
|
var result = await _leadService.ActualizarProductoAsync(id, producto);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}/contacto")]
|
||||||
|
public async Task<IActionResult> ActualizarContacto(int id, [FromBody] ContactoUpdateDto dto)
|
||||||
|
{
|
||||||
|
var result = await _leadService.ActualizarContactoAsync(id, dto.Nombre ?? "", dto.Mail ?? "", dto.Telefono ?? "", dto.Rut ?? "");
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id}/perder")]
|
||||||
|
public async Task<IActionResult> IngresarLeadPerdido(int id, [FromQuery] int motivo, [FromQuery] int estado)
|
||||||
|
{
|
||||||
|
var result = await _leadService.IngresarLeadPerdidoAsync(id, motivo, estado);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id}/pago")]
|
||||||
|
public async Task<IActionResult> IngresarPago(int id, [FromBody] PagoLeadDto dto)
|
||||||
|
{
|
||||||
|
var result = await _leadService.IngresarPagoAsync(dto.LeadId, dto.CotizacionId, dto.FormaPago, dto.Monto, dto.CodigoAutorizacion ?? "", dto.DigitoTarjeta ?? "", dto.Cuotas);
|
||||||
|
return Ok(new { mensaje = result });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||||||
using Ventas.Infrastructure.Data;
|
using Ventas.Infrastructure.Data;
|
||||||
using Ventas.Infrastructure.Repositories;
|
using Ventas.Infrastructure.Repositories;
|
||||||
using Ventas.Core.Interfaces;
|
using Ventas.Core.Interfaces;
|
||||||
|
using Ventas.Services;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -21,7 +22,16 @@ builder.Services.AddScoped<ILeadRepository>(sp =>
|
|||||||
builder.Services.AddScoped<ILeadQueryRepository>(sp =>
|
builder.Services.AddScoped<ILeadQueryRepository>(sp =>
|
||||||
new LeadQueryRepository(connectionString));
|
new LeadQueryRepository(connectionString));
|
||||||
|
|
||||||
|
builder.Services.AddScoped<LeadService>(sp =>
|
||||||
|
new LeadService(connectionString));
|
||||||
|
builder.Services.AddScoped<UsuarioService>(sp =>
|
||||||
|
new UsuarioService(connectionString));
|
||||||
|
|
||||||
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
|
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
|
||||||
|
var jwtExpiration = int.Parse(builder.Configuration["Jwt:ExpirationMinutes"] ?? "30");
|
||||||
|
builder.Services.AddScoped<JwtService>(sp =>
|
||||||
|
new JwtService(jwtSecret, jwtExpiration));
|
||||||
|
|
||||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
.AddJwtBearer(options =>
|
.AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace Ventas.Services;
|
||||||
|
|
||||||
|
public class JwtService
|
||||||
|
{
|
||||||
|
private readonly string _secret;
|
||||||
|
private readonly int _expirationMinutes;
|
||||||
|
|
||||||
|
public JwtService(string secret, int expirationMinutes)
|
||||||
|
{
|
||||||
|
_secret = secret;
|
||||||
|
_expirationMinutes = expirationMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateToken(string usuarioId, string nombre, string sede)
|
||||||
|
{
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret));
|
||||||
|
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var claims = new[]
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, usuarioId),
|
||||||
|
new Claim(ClaimTypes.Name, nombre),
|
||||||
|
new Claim("sede", sede)
|
||||||
|
};
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
claims: claims,
|
||||||
|
expires: DateTime.UtcNow.AddMinutes(_expirationMinutes),
|
||||||
|
signingCredentials: credentials);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
using Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
namespace Ventas.Services;
|
||||||
|
|
||||||
|
public class LeadService
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public LeadService(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarAsync(int ejecutivo, int estado, int dias)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadV3",
|
||||||
|
new { ejecutivo, estadolead = estado, filtro = dias },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarIDAsync(int id)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadID",
|
||||||
|
new { id },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarNuevosAsync(int ejecutivo)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadNuevos",
|
||||||
|
new { ejecutivo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarAsync(LeadCreateDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.GrabaLead",
|
||||||
|
new { nombrelead = dto.Nombre, maillead = dto.Mail, telefonolead = dto.Telefono, productolead = dto.Producto, contactolead = dto.Contacto, ejecutivoid = dto.EjecutivoId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarV2Async(LeadCreateDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var result = await connection.QuerySingleOrDefaultAsync<string>(
|
||||||
|
"sige_sam_v3.GrabaLead",
|
||||||
|
new { nombrelead = dto.Nombre, maillead = dto.Mail, telefonolead = dto.Telefono, productolead = dto.Producto, contactolead = dto.Contacto, ejecutivoid = dto.EjecutivoId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return result ?? "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarPagoAsync(int lead, int coti, string pago, int monto, string cod, string dig, int cuota)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.GrabaPagoLead",
|
||||||
|
new { leadid = lead, cotiid = coti, formapago = pago, valor = monto, codauto = cod, digtar = dig, cantcouta = cuota },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> ActualizarProductoAsync(int leadId, string producto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sam.ActualuzarLeadProducto",
|
||||||
|
new { leadid = leadId, productlead = producto },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> MontosAsync(int ejecutivo)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadMontos",
|
||||||
|
new { ejecutivo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> ActividadesAsync(int leadId, string tipo)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarActividadesLead",
|
||||||
|
new { id = leadId, tipoactividad = tipo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarActividadAsync(int leadId, string tipo, string descripcion, string usuarioId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.GrabaActividadesLead",
|
||||||
|
new { leadid = leadId, tipo, descripcion, usuarioid = usuarioId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> EstadoUpdateAsync(int leadId, int estadoId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizarEstadoLead",
|
||||||
|
new { leadid = leadId, estadolead = estadoId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> MotivosPerdidoAsync()
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarMotivoLeadPerdido",
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarLeadPerdidoAsync(int leadId, int motivo, int estado)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.Lead_Ingresar_Perdido",
|
||||||
|
new { leadid = leadId, motivo, estado },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> ActualizarContactoAsync(int leadId, string nombre, string mail, string fono, string rut)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizaLeadContacto",
|
||||||
|
new { leadid = leadId, nombrecontacto = nombre, mailcontacto = mail, fonocontacto = fono, rutcontacto = rut },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
using Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
namespace Ventas.Services;
|
||||||
|
|
||||||
|
public class UsuarioService
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public UsuarioService(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoginResponse?> LoginAsync(LoginRequest request)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var data = await connection.QueryAsync(
|
||||||
|
"sam.BuscarUsuario",
|
||||||
|
new { userid = request.Rut, passid = request.Clave },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
var user = data.FirstOrDefault();
|
||||||
|
if (user == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var dict = (IDictionary<string, object>)user;
|
||||||
|
return new LoginResponse
|
||||||
|
{
|
||||||
|
Nombre = dict["Nombres"]?.ToString() ?? "",
|
||||||
|
Sede = dict["idSede"]?.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoginResponse?> PerfilAsync(string usuarioId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var data = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarPerfilUsuario",
|
||||||
|
new { usuario = usuarioId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
var user = data.FirstOrDefault();
|
||||||
|
if (user == null) return null;
|
||||||
|
|
||||||
|
var dict = (IDictionary<string, object>)user;
|
||||||
|
return new LoginResponse
|
||||||
|
{
|
||||||
|
Nombre = dict["Nombres"]?.ToString() ?? "",
|
||||||
|
Sede = dict["idSede"]?.ToString(),
|
||||||
|
Perfil = dict["Perfil"]?.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user