feat: core entities, infrastructure, and lead repositories
- 25 domain entities mapped from original Datos/ classes - 4 enums (EstadoLead, TipoPago, TipoDocumento, TipoDescuento) - DTOs for Lead, Auth flows - 6 repository interfaces - VentasDbContext with EF Core + Npgsql - LeadRepository (command SPs) and LeadQueryRepository (query SPs) with Dapper - Program.cs with JWT auth, CORS, DI setup - appsettings.json with connection string - .gitignore for bin/obj/node_modules - ROADMAP.md for daily progress tracking
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
|||||||
|
# .NET
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.dll
|
||||||
|
*.pdb
|
||||||
|
*.exe
|
||||||
|
*.runtimeconfig.json
|
||||||
|
*.deps.json
|
||||||
|
*.staticwebassets.endpoints.json
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Node
|
||||||
|
node_modules/
|
||||||
|
.next/
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
*.env.local
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
# Roadmap — Migración ModuloVentas
|
||||||
|
|
||||||
|
> **Proyecto:** rm-ventas
|
||||||
|
> **Original:** `/home/juan/dev/ventas` (.NET Framework 4.7.2 / WebForms / MySQL)
|
||||||
|
> **Destino:** .NET 10 + PostgreSQL + Next.js
|
||||||
|
> **Inicio:** Julio 2026
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estado Actual
|
||||||
|
|
||||||
|
| Componente | Estado |
|
||||||
|
|-----------|--------|
|
||||||
|
| Backend .NET 10 — Skeleton (sln + 4 proyectos + NuGet) | ✅ CREADO |
|
||||||
|
| Entidades / DTOs / Interfaces (Ventas.Core) | ✅ CREADO |
|
||||||
|
| Infrastructure (EF Core + Dapper + Repos) | ✅ PARCIAL (DbContext + LeadRepository listos) |
|
||||||
|
| Services (lógica de negocio) | ❌ PENDIENTE |
|
||||||
|
| API Controllers | ❌ PENDIENTE |
|
||||||
|
| Auth JWT | ❌ PENDIENTE |
|
||||||
|
| Reportes QuestPDF (17 reportes) | ❌ PENDIENTE |
|
||||||
|
| ServicesExternos.API | ❌ PENDIENTE |
|
||||||
|
| Frontend Next.js | ❌ PENDIENTE |
|
||||||
|
| Contenedores (Docker) | ❌ PENDIENTE |
|
||||||
|
| Tests E2E | ❌ PENDIENTE |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist por Fase
|
||||||
|
|
||||||
|
### FASE 1: BACKEND .NET 10 — API REST (~6-8 semanas)
|
||||||
|
|
||||||
|
- [x] **1.1** Crear solución + proyectos base
|
||||||
|
- [x] **1.2 Ventas.Core — Entidades y DTOs** (~1 sem)
|
||||||
|
- [x] Lead.cs + resto entidades (25 clases desde `Datos/`)
|
||||||
|
- [x] DTOs request/response (LeadDto, LoginRequest, etc.)
|
||||||
|
- [x] Enums (EstadoLead, TipoPago, TipoDocumento, TipoDescuento)
|
||||||
|
- [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)
|
||||||
|
- [ ] **1.4 Ventas.Services — Lógica de Negocio** (~2 sem)
|
||||||
|
- [ ] LeadService.cs + resto servicios (~15)
|
||||||
|
- [ ] **1.5 Ventas.API — Controladores REST** (~1 sem)
|
||||||
|
- [ ] AuthController.cs
|
||||||
|
- [ ] LeadController.cs + resto controllers (~20)
|
||||||
|
- [ ] Program.cs completo (DI, JWT, CORS)
|
||||||
|
- [ ] appsettings.json con connection strings
|
||||||
|
- [ ] **1.6 Auth JWT** (~3 días)
|
||||||
|
- [ ] JwtMiddleware.cs
|
||||||
|
- [ ] Login endpoint funcional
|
||||||
|
- [ ] Claims → cookies HttpOnly
|
||||||
|
- [ ] **1.7 Reportes QuestPDF** (~2-3 sem)
|
||||||
|
- [ ] ReportService.cs (base)
|
||||||
|
- [ ] 17 reportes (Contrato, Cotización, Arqueo, etc.)
|
||||||
|
- [ ] Dockerfile Backend
|
||||||
|
|
||||||
|
### FASE 2: SERVICES EXTERNOS API (~2-3 semanas)
|
||||||
|
|
||||||
|
- [ ] **2.0 Setup**
|
||||||
|
- [ ] ServicesExternos.sln + proyectos
|
||||||
|
- [ ] Program.cs + Dockerfile
|
||||||
|
- [ ] **2.1 LibreDTE** (~1 sem)
|
||||||
|
- [ ] **2.2 Transbank Webpay** (~1 sem)
|
||||||
|
- [ ] **2.3 Email con MailKit** (~2 días)
|
||||||
|
|
||||||
|
### FASE 3: FRONTEND NEXT.JS (~6-8 semanas)
|
||||||
|
|
||||||
|
- [ ] **3.1 Setup** (create-next-app, packages, config)
|
||||||
|
- [ ] **3.2 Layout Principal** (~1 sem)
|
||||||
|
- [ ] layout.tsx (sidebar + header = SAM.Master)
|
||||||
|
- [ ] Sidebar.tsx, Header.tsx
|
||||||
|
- [ ] CSS original (style.css, ichn.css, etc.)
|
||||||
|
- [ ] **3.3 Login + Auth** (~3 días)
|
||||||
|
- [ ] **3.4 Dashboard** (~3 días)
|
||||||
|
- [ ] **3.5 Módulo Leads** (~1 sem) — 3 páginas
|
||||||
|
- [ ] **3.6 Módulo Cotizaciones/Pagos** (~1 sem)
|
||||||
|
- [ ] **3.7 Módulo Empresas** (~1 sem) — 3 páginas
|
||||||
|
- [ ] **3.8 Resto páginas** (~2-3 sem)
|
||||||
|
- Arqueo, Cursos, Alumnos
|
||||||
|
- Reportes (3), Autorizador, Contacto
|
||||||
|
- [ ] Dockerfile Frontend
|
||||||
|
|
||||||
|
### FASE 4: CONTENEDORES (~1 semana)
|
||||||
|
|
||||||
|
- [ ] docker-compose.yml (backend-api + services-externos + frontend)
|
||||||
|
- [ ] .env.example
|
||||||
|
- [ ] .gitignore
|
||||||
|
|
||||||
|
### FASE 5: PRUEBAS (~2-3 semanas)
|
||||||
|
|
||||||
|
- [ ] Unit tests backend (xUnit + Moq)
|
||||||
|
- [ ] Integration tests (TestContainers + PostgreSQL)
|
||||||
|
- [ ] Playwright E2E (20 escenarios)
|
||||||
|
- [ ] Visual regression tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bitácora Diaria
|
||||||
|
|
||||||
|
| 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 |
|
||||||
|
| | | | |
|
||||||
|
| | | | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Próximos Pasos Inmediatos
|
||||||
|
|
||||||
|
1. ~~Completar `Ventas.Core/Entities/`~~ ✅
|
||||||
|
2. ~~Configurar `VentasDbContext`~~ ✅
|
||||||
|
3. ~~Crear `LeadRepository` + `LeadQueryRepository`~~ ✅
|
||||||
|
4. **Agregar referencia Infrastructure a Ventas.API** ✅
|
||||||
|
5. **Configurar JWT + CORS + DI en Program.cs** ✅
|
||||||
|
6. **Actualizar `appsettings.json`** con connection string ✅
|
||||||
|
7. **Seguir repositorios** por prioridad: Contrato → Cotizacion → Alumno → Usuario → Auth
|
||||||
|
8. **Crear Controllers** (empezar con AuthController + LeadController)
|
||||||
|
9. **Probar compilación** con `dotnet build`
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<Solution>
|
||||||
|
<Folder Name="/src/">
|
||||||
|
<Project Path="src/Ventas.API/Ventas.API.csproj" />
|
||||||
|
<Project Path="src/Ventas.Core/Ventas.Core.csproj" />
|
||||||
|
<Project Path="src/Ventas.Infrastructure/Ventas.Infrastructure.csproj" />
|
||||||
|
<Project Path="src/Ventas.Services/Ventas.Services.csproj" />
|
||||||
|
</Folder>
|
||||||
|
</Solution>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Ventas.Infrastructure.Data;
|
||||||
|
using Ventas.Infrastructure.Repositories;
|
||||||
|
using Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
var connectionString = builder.Configuration.GetConnectionString("Default")!;
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<VentasDbContext>(options =>
|
||||||
|
options.UseNpgsql(connectionString));
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ILeadRepository>(sp =>
|
||||||
|
new LeadRepository(connectionString));
|
||||||
|
builder.Services.AddScoped<ILeadQueryRepository>(sp =>
|
||||||
|
new LeadQueryRepository(connectionString));
|
||||||
|
|
||||||
|
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
|
||||||
|
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddDefaultPolicy(policy =>
|
||||||
|
{
|
||||||
|
policy.AllowAnyOrigin()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.MapOpenApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseCors();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "http://localhost:5087",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ventas.Core\Ventas.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\Ventas.Infrastructure\Ventas.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\Ventas.Services\Ventas.Services.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@Ventas.API_HostAddress = http://localhost:5087
|
||||||
|
|
||||||
|
GET {{Ventas.API_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Default": "Host=192.168.0.254;Port=5432;Database=ichn;Username=postgres;Password=apoca11;Pooling=true;Maximum Pool Size=100;"
|
||||||
|
},
|
||||||
|
"Jwt": {
|
||||||
|
"Secret": "",
|
||||||
|
"ExpirationMinutes": 30
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
namespace Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
public class LeadCreateDto
|
||||||
|
{
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Telefono { get; set; }
|
||||||
|
public string? Producto { get; set; }
|
||||||
|
public int Contacto { get; set; }
|
||||||
|
public int EjecutivoId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LeadResponseDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Telefono { get; set; }
|
||||||
|
public string? Producto { get; set; }
|
||||||
|
public string? Ejecutivo { get; set; }
|
||||||
|
public string? Estado { get; set; }
|
||||||
|
public DateTime? FechaCreacion { get; set; }
|
||||||
|
public string? RutContacto { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LeadBuscarRequest
|
||||||
|
{
|
||||||
|
public int? Ejecutivo { get; set; }
|
||||||
|
public int? Estado { get; set; }
|
||||||
|
public int? Dias { get; set; }
|
||||||
|
public string? TipoFiltro { get; set; }
|
||||||
|
public string? ValorBusqueda { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContactoUpdateDto
|
||||||
|
{
|
||||||
|
public string? Nombre { get; set; }
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Telefono { get; set; }
|
||||||
|
public string? Rut { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ActividadCreateDto
|
||||||
|
{
|
||||||
|
public string Tipo { get; set; } = string.Empty;
|
||||||
|
public string Descripcion { get; set; } = string.Empty;
|
||||||
|
public DateTime? FechaPlanificada { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PagoLeadDto
|
||||||
|
{
|
||||||
|
public int LeadId { get; set; }
|
||||||
|
public int CotizacionId { get; set; }
|
||||||
|
public string FormaPago { get; set; } = string.Empty;
|
||||||
|
public int Monto { get; set; }
|
||||||
|
public string? CodigoAutorizacion { get; set; }
|
||||||
|
public string? DigitoTarjeta { get; set; }
|
||||||
|
public int Cuotas { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
public class LoginRequest
|
||||||
|
{
|
||||||
|
public string Rut { get; set; } = string.Empty;
|
||||||
|
public string Clave { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
public class LoginResponse
|
||||||
|
{
|
||||||
|
public string Token { get; set; } = string.Empty;
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Sede { get; set; }
|
||||||
|
public string? Perfil { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Actividad
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int LeadId { get; set; }
|
||||||
|
public string? Tipo { get; set; }
|
||||||
|
public string? Descripcion { get; set; }
|
||||||
|
public string? UsuarioId { get; set; }
|
||||||
|
public DateTime? FechaCreacion { get; set; }
|
||||||
|
public DateTime? FechaPlanificada { get; set; }
|
||||||
|
public int? Estado { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Alumno
|
||||||
|
{
|
||||||
|
public string Rut { get; set; } = string.Empty;
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Paterno { get; set; }
|
||||||
|
public string? Materno { get; set; }
|
||||||
|
public string? Direccion { get; set; }
|
||||||
|
public string? Comuna { get; set; }
|
||||||
|
public int? ComunaId { get; set; }
|
||||||
|
public int? Nacionalidad { get; set; }
|
||||||
|
public string? FechaNacimiento { get; set; }
|
||||||
|
public string? Telefono { get; set; }
|
||||||
|
public string? Email { get; set; }
|
||||||
|
public string? Clave { get; set; }
|
||||||
|
public int? ColegioId { get; set; }
|
||||||
|
public int? ProfesionId { get; set; }
|
||||||
|
public int? OcupacionId { get; set; }
|
||||||
|
public string? ProfesionOficio { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class ArqueoCaja
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? UsuarioId { get; set; }
|
||||||
|
public DateTime? Fecha { get; set; }
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public string? Tipo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Comuna
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public int? RegionId { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Contrato
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? CotizacionId { get; set; }
|
||||||
|
public int? BoletaCKT { get; set; }
|
||||||
|
public DateTime? FechaContrato { get; set; }
|
||||||
|
public int? BoletaId { get; set; }
|
||||||
|
public int? VendedorId { get; set; }
|
||||||
|
public string? EmpresaId { get; set; }
|
||||||
|
public int? TipoVentaId { get; set; }
|
||||||
|
public int? FacturaId { get; set; }
|
||||||
|
public int? CantidadCursos { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class ContratoDetalle
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int ContratoId { get; set; }
|
||||||
|
public string? EmpresaId { get; set; }
|
||||||
|
public string? AlumnoId { get; set; }
|
||||||
|
public string? CursoId { get; set; }
|
||||||
|
public DateTime? Fecha { get; set; }
|
||||||
|
public int? VendedorId { get; set; }
|
||||||
|
public int? TipoRegistro { get; set; }
|
||||||
|
public int? TipoAlumno { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Cotizacion
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? LeadId { get; set; }
|
||||||
|
public string? Apoderado { get; set; }
|
||||||
|
public string? Vendedor { get; set; }
|
||||||
|
public int? SolicitudDescuentoId { get; set; }
|
||||||
|
public int? DescuentoId { get; set; }
|
||||||
|
public int? TipoDescuento { get; set; }
|
||||||
|
public string? Fecha { get; set; }
|
||||||
|
public int? Alumnos { get; set; }
|
||||||
|
public int? Curso { get; set; }
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public string? Validez { get; set; }
|
||||||
|
public string? EmpresaId { get; set; }
|
||||||
|
public int? MontoEmpresa { get; set; }
|
||||||
|
public int? MontoOtic { get; set; }
|
||||||
|
public int? MontoAlumno { get; set; }
|
||||||
|
public int? CotizacionTipo { get; set; }
|
||||||
|
public int? Estado { get; set; }
|
||||||
|
public string? Motivo { get; set; }
|
||||||
|
public string? OticId { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class CotizacionDetalle
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int CotizacionId { get; set; }
|
||||||
|
public string? AlumnoId { get; set; }
|
||||||
|
public string? ApoderadoId { get; set; }
|
||||||
|
public int? CursoId { get; set; }
|
||||||
|
public int? ProgramaId { get; set; }
|
||||||
|
public int? Cantidad { get; set; }
|
||||||
|
public int? TarifaId { get; set; }
|
||||||
|
public int? SedeId { get; set; }
|
||||||
|
public int? MontoAlumno { get; set; }
|
||||||
|
public int? MontoEmpresa { get; set; }
|
||||||
|
public int? MontoOtic { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Curso
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public int? ProgramaId { get; set; }
|
||||||
|
public int? Producto { get; set; }
|
||||||
|
public int? Duracion { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Descuento
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public DateTime? Inicio { get; set; }
|
||||||
|
public DateTime? Termino { get; set; }
|
||||||
|
public int? TipoDescuento { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Diagnostico
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? AlumnoId { get; set; }
|
||||||
|
public int? CursoId { get; set; }
|
||||||
|
public int? LeadId { get; set; }
|
||||||
|
public string? UsuarioId { get; set; }
|
||||||
|
public DateTime? Fecha { get; set; }
|
||||||
|
public string? Resultado { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Documento
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? NumeroInterno { get; set; }
|
||||||
|
public int? ContratoId { get; set; }
|
||||||
|
public string? EmpresaId { get; set; }
|
||||||
|
public int? TipoId { get; set; }
|
||||||
|
public int? ValorTotal { get; set; }
|
||||||
|
public int? CantidadCursos { get; set; }
|
||||||
|
public string? Glosa { get; set; }
|
||||||
|
public string? Ubicacion { get; set; }
|
||||||
|
public string? Usuario { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Empresa
|
||||||
|
{
|
||||||
|
public string Rut { get; set; } = string.Empty;
|
||||||
|
public string RazonSocial { get; set; } = string.Empty;
|
||||||
|
public string? Direccion { get; set; }
|
||||||
|
public string? ComunaId { get; set; }
|
||||||
|
public int? TipoId { get; set; }
|
||||||
|
public int? TamagnoId { get; set; }
|
||||||
|
public string? GiroNombre { get; set; }
|
||||||
|
public string? Contacto { get; set; }
|
||||||
|
public int? Fono { get; set; }
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Origen { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Horario
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? BloqueId { get; set; }
|
||||||
|
public string? HoraInicio { get; set; }
|
||||||
|
public string? HoraTermino { get; set; }
|
||||||
|
public int? SedeId { get; set; }
|
||||||
|
public int? JornadaId { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Jornada
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Lead
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Telefono { get; set; }
|
||||||
|
public string? Producto { get; set; }
|
||||||
|
public int? Contacto { get; set; }
|
||||||
|
public int? EjecutivoId { get; set; }
|
||||||
|
public int? Estado { get; set; }
|
||||||
|
public DateTime? FechaCreacion { get; set; }
|
||||||
|
public string? RutContacto { get; set; }
|
||||||
|
public string? AlumnoId { get; set; }
|
||||||
|
public string? ClienteId { get; set; }
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public string? MensajeRecordatorio { get; set; }
|
||||||
|
public DateTime? FechaProximaGestion { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class MotivoPerdido
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Programa
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Tipo { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Propuesta
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? TipoPropuesta { get; set; }
|
||||||
|
public int? Estado { get; set; }
|
||||||
|
public int? TipoVenta { get; set; }
|
||||||
|
public string? Vendedor { get; set; }
|
||||||
|
public DateTime? Fecha { get; set; }
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public string? OticId { get; set; }
|
||||||
|
public string? EnvioLibre { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Region
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public int? Numero { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Sala
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public int? SedeId { get; set; }
|
||||||
|
public int? Capacidad { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Sede
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Direccion { get; set; }
|
||||||
|
public int? ComunaId { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Tarifa
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? Producto { get; set; }
|
||||||
|
public int? ProgramaId { get; set; }
|
||||||
|
public int? JornadaId { get; set; }
|
||||||
|
public int? SedeId { get; set; }
|
||||||
|
public int? Monto { get; set; }
|
||||||
|
public string? Fecha { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class TransbankInfo
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Token { get; set; }
|
||||||
|
public string? AccountingDate { get; set; }
|
||||||
|
public string? BuyOrder { get; set; }
|
||||||
|
public string? CardNumber { get; set; }
|
||||||
|
public string? AuthorizationCode { get; set; }
|
||||||
|
public string? PaymentTypeCode { get; set; }
|
||||||
|
public string? ResponseCode { get; set; }
|
||||||
|
public string? SharesNumber { get; set; }
|
||||||
|
public int? Amount { get; set; }
|
||||||
|
public string? CommerceCode { get; set; }
|
||||||
|
public string? SessionId { get; set; }
|
||||||
|
public DateTime? TransactionDate { get; set; }
|
||||||
|
public string? Vci { get; set; }
|
||||||
|
public string? Estado { get; set; }
|
||||||
|
public int? VendedorId { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace Ventas.Core.Entities;
|
||||||
|
|
||||||
|
public class Usuario
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Nombre { get; set; } = string.Empty;
|
||||||
|
public string? Paterno { get; set; }
|
||||||
|
public string? Materno { get; set; }
|
||||||
|
public string? Mail { get; set; }
|
||||||
|
public string? Fono1 { get; set; }
|
||||||
|
public string? Fono2 { get; set; }
|
||||||
|
public string? Clave { get; set; }
|
||||||
|
public int? SedeId { get; set; }
|
||||||
|
public string? Perfil { get; set; }
|
||||||
|
public bool? Activo { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Ventas.Core.Enums;
|
||||||
|
|
||||||
|
public enum EstadoLead
|
||||||
|
{
|
||||||
|
Nuevo = 1,
|
||||||
|
Contactado = 2,
|
||||||
|
EnProceso = 3,
|
||||||
|
Cotizado = 4,
|
||||||
|
Ganado = 5,
|
||||||
|
Perdido = 6,
|
||||||
|
Archivado = 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ventas.Core.Enums;
|
||||||
|
|
||||||
|
public enum TipoDescuento
|
||||||
|
{
|
||||||
|
Porcentaje = 1,
|
||||||
|
MontoFijo = 2,
|
||||||
|
Promocion = 3,
|
||||||
|
Lider = 4,
|
||||||
|
Summer = 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ventas.Core.Enums;
|
||||||
|
|
||||||
|
public enum TipoDocumento
|
||||||
|
{
|
||||||
|
Boleta = 1,
|
||||||
|
Factura = 2,
|
||||||
|
OrdenCompra = 3,
|
||||||
|
Sence = 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ventas.Core.Enums;
|
||||||
|
|
||||||
|
public enum TipoPago
|
||||||
|
{
|
||||||
|
Efectivo = 1,
|
||||||
|
TarjetaCredito = 2,
|
||||||
|
TarjetaDebito = 3,
|
||||||
|
Transferencia = 4,
|
||||||
|
Webpay = 5,
|
||||||
|
Cheque = 6
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface IAlumnoRepository
|
||||||
|
{
|
||||||
|
Task<string> IngresarV2Async(string rut, string nombre, string paterno, string materno, string direccion, string comuna, string fecha, string fono, string mail, int ocupacion, string profeOficio);
|
||||||
|
Task<string> IngresarV3Async(string rut, string nombre, string paterno, string materno, string direccion, string comuna, string fecha, string fono, string mail, int ocupacion, string profeOficio);
|
||||||
|
Task<string> 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);
|
||||||
|
Task<string> IngresarApoderadoAsync(string rutApoderado, string rutAlumno, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fono, string mail);
|
||||||
|
Task<string> ActualizarApoderadoAsync(string rutApoderado, string rutAlumno, string nombre, string paterno, string materno, string direccion, string comuna, int nacionalidad, string fono, string mail);
|
||||||
|
Task<string> AsignarLeadDiagnosticoAsync(int diagnosticoId, int leadId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface IContratoRepository
|
||||||
|
{
|
||||||
|
Task<string> IngresarAsync(int cotizacionId, int boletaCKT, string fechaContrato, int boletaId, int vendedorId);
|
||||||
|
Task<string> IngresarDetalleAsync(int contratoId, string empresaId, string alumnoId, string cursoId, string fecha, int vendedor, int registroAcademico, int alumnoTipo);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface ICotizacionRepository
|
||||||
|
{
|
||||||
|
Task<string> PersonaIngresarAsync(string apoderado, string vendedor, int solicitudDescuento, int descuento, int tipoDescuento, string fecha, int alumnos, int curso, int monto, string validez, int leadId);
|
||||||
|
Task<string> PersonaPagarAsync(int cotizacionId);
|
||||||
|
Task<string> DesactivarAsync(int cotizacionId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Ventas.Core.Entities;
|
||||||
|
|
||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface ILeadQueryRepository
|
||||||
|
{
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarAsync(int ejecutivo, int estado, int cantidadDias);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarIDAsync(int idLead);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarNuevosAsync(int ejecutivo);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarGestionAsync(int ejecutivo, DateTime fecha);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarMailAsync(string mail);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarTituloAsync(string nombre);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarXestadoAsync(int ejecutivo, int estado);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarXfiltroAsync(string tipo, string busqueda);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarXinformeAsync(string tipo);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> MontosAsync(int ejecutivo);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> ActividadesAsync(int leadId, string tipo);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> MotivosPerdidoAsync();
|
||||||
|
Task<string> BuscarContactoAsync(int leadId);
|
||||||
|
Task<IEnumerable<Dictionary<string, object>>> BuscarResumenLeadEjeAsync(string ejecutivoId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Ventas.Core.DTOs;
|
||||||
|
|
||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface ILeadRepository
|
||||||
|
{
|
||||||
|
Task<string> IngresarAsync(LeadCreateDto dto);
|
||||||
|
Task<string> IngresarV2Async(LeadCreateDto dto);
|
||||||
|
Task<string> IngresarPagoAsync(PagoLeadDto dto);
|
||||||
|
Task<string> ActualizarProductoAsync(int leadId, string producto);
|
||||||
|
Task<string> EstadoUpdateAsync(int leadId, int estadoId);
|
||||||
|
Task<string> IngresarLeadPerdidoAsync(int leadId, int motivo, int estado);
|
||||||
|
Task<string> IngresarActividadAsync(int leadId, ActividadCreateDto dto);
|
||||||
|
Task<string> IngresarActividadPlanAsync(int leadId, DateTime fecha, string actividad);
|
||||||
|
Task<string> ActualizarActividadPlanAsync(int id, DateTime fecha, string actividad, int estado);
|
||||||
|
Task<string> ActualizarContactoAsync(int leadId, ContactoUpdateDto dto);
|
||||||
|
Task<string> IngresarAlumnoAsync(int leadId, string rut);
|
||||||
|
Task<string> AgregarClienteAsync(int lead, string apoderadoId);
|
||||||
|
Task<string> MensajeRecordarAsync(int leadId, string mensaje, DateTime fechaProxima);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
public interface IUsuarioRepository
|
||||||
|
{
|
||||||
|
Task<string> BuscarAsync(string usuario, string clave);
|
||||||
|
Task<string> InfoAsync(string usuario);
|
||||||
|
Task<string> PerfilAsync(string usuario);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ventas.Core.Entities;
|
||||||
|
|
||||||
|
namespace Ventas.Infrastructure.Data;
|
||||||
|
|
||||||
|
public class VentasDbContext : DbContext
|
||||||
|
{
|
||||||
|
public VentasDbContext(DbContextOptions<VentasDbContext> options) : base(options) { }
|
||||||
|
|
||||||
|
public DbSet<Lead> Leads { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Lead>(e =>
|
||||||
|
{
|
||||||
|
e.HasNoKey();
|
||||||
|
e.ToView(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
using Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
namespace Ventas.Infrastructure.Repositories;
|
||||||
|
|
||||||
|
public class LeadQueryRepository : ILeadQueryRepository
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public LeadQueryRepository(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarAsync(int ejecutivo, int estado, int cantidadDias)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadV3",
|
||||||
|
new { ejecutivo = ejecutivo, estadolead = estado, filtro = cantidadDias },
|
||||||
|
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 idLead)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadID",
|
||||||
|
new { id = idLead },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<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 = ejecutivo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarGestionAsync(int ejecutivo, DateTime fecha)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadGestion",
|
||||||
|
new { ejecutivoid = ejecutivo, fecha = fecha },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarMailAsync(string mail)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadMail",
|
||||||
|
new { mailbuscar = mail },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarTituloAsync(string nombre)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.BuscarLeadTitulo",
|
||||||
|
new { nombrebuscar = nombre },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXestadoAsync(int ejecutivo, int estado)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.Lead_buscarXestado",
|
||||||
|
new { userid = ejecutivo, estadoid = estado },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXfiltroAsync(string tipo, string busqueda)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.Lead_buscarXfiltro",
|
||||||
|
new { tipofiltro = tipo, valorbuscar = busqueda },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXinformeAsync(string tipo)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.Lead_InformeXhoy",
|
||||||
|
new { tipoinforme = tipo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ejecutivo },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<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>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
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>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> BuscarContactoAsync(int leadId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
return await connection.QuerySingleOrDefaultAsync<string>(
|
||||||
|
"sige_sam_v3.BuscarLeadContacto",
|
||||||
|
new { id = leadId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Dictionary<string, object>>> BuscarResumenLeadEjeAsync(string ejecutivoId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"sige_sam_v3.LeadCantidadEjecutivoNuevo",
|
||||||
|
new { userid = ejecutivoId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)r);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
using Ventas.Core.DTOs;
|
||||||
|
using Ventas.Core.Interfaces;
|
||||||
|
|
||||||
|
namespace Ventas.Infrastructure.Repositories;
|
||||||
|
|
||||||
|
public class LeadRepository : ILeadRepository
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public LeadRepository(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarAsync(LeadCreateDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
using var reader = await connection.ExecuteReaderAsync(
|
||||||
|
"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(PagoLeadDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.GrabaPagoLead",
|
||||||
|
new
|
||||||
|
{
|
||||||
|
leadid = dto.LeadId,
|
||||||
|
cotiid = dto.CotizacionId,
|
||||||
|
formapago = dto.FormaPago,
|
||||||
|
valor = dto.Monto,
|
||||||
|
codauto = dto.CodigoAutorizacion,
|
||||||
|
digtar = dto.DigitoTarjeta,
|
||||||
|
cantcouta = dto.Cuotas
|
||||||
|
},
|
||||||
|
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<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<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 = motivo, estado = estado },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarActividadAsync(int leadId, ActividadCreateDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.GrabaActividadesLead",
|
||||||
|
new { leadid = leadId, tipo = dto.Tipo, descripcion = dto.Descripcion, usuarioid = "" },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarActividadPlanAsync(int leadId, DateTime fecha, string actividad)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.IngresarActividadPlanLead",
|
||||||
|
new { leadid = leadId, fechaplan = fecha, descripcion = actividad },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> ActualizarActividadPlanAsync(int id, DateTime fecha, string actividad, int estado)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizalLeadPlan",
|
||||||
|
new { fechaplan = fecha, gestion = actividad, estadoplan = estado, planid = id },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> ActualizarContactoAsync(int leadId, ContactoUpdateDto dto)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizaLeadContacto",
|
||||||
|
new { leadid = leadId, nombrecontacto = dto.Nombre, mailcontacto = dto.Mail, fonocontacto = dto.Telefono, rutcontacto = dto.Rut },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> IngresarAlumnoAsync(int leadId, string rut)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizarAlumnoLead",
|
||||||
|
new { leadid = leadId, alumnoid = rut },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> AgregarClienteAsync(int lead, string apoderadoId)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizarLeadCliente",
|
||||||
|
new { leadid = lead, apoid = apoderadoId },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> MensajeRecordarAsync(int leadId, string mensaje, DateTime fechaProxima)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
await connection.ExecuteAsync(
|
||||||
|
"sige_sam_v3.ActualizarRecordarLead",
|
||||||
|
new { leadid = leadId, mensajelead = mensaje, fechanextgestion = fechaProxima },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ventas.Core\Ventas.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Dapper" Version="2.1.79" />
|
||||||
|
<PackageReference Include="MailKit" Version="4.17.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.9" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
|
||||||
|
<PackageReference Include="QuestPDF" Version="2026.7.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ventas.Core\Ventas.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\Ventas.Infrastructure\Ventas.Infrastructure.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user