Sistema de gestión empresarial para PoliMarket desarrollado con .NET 9 y Clean Architecture. Implementa módulos de Ventas, Inventario, Seguridad y Logística con integración completa entre módulos.
PoliMarket-Backend es una API RESTful robusta que proporciona:
- Gestión de Ventas: CRUD de clientes, facturación con validación de stock en tiempo real
- Gestión de Inventario: Consulta de productos, verificación de stock, trazabilidad de movimientos
- Seguridad: Autenticación de usuarios, gestión de roles y permisos
- Integración de Módulos: Validación cross-module (ventas valida stock, registra movimientos)
| RF | Descripción | Estado | Módulo |
|---|---|---|---|
| RF01 | Gestión Centralizada de Autorizaciones de Usuario | ✅ | Security |
| RF02 | Inicio de Sesión de Usuarios | ✅ | Security |
| RF03 | Consulta en Tiempo Real de Disponibilidad de Productos | ✅ | Inventory + Sales |
| RF04 | Registro Automatizado de Salida de Stock por Venta | ✅ | Sales + Inventory |
| RF05 | Generación Automática de Órdenes de Entrega | ✅ | Logistics |
El proyecto sigue los principios de Clean Architecture con separación clara de responsabilidades:
┌──────────────────────────────────────────────────────┐
│ Presentation Layer │
│ (Controllers - API REST) │
│ │
│ SecurityController | InventoryController | │
│ SalesController | LogisticsController │
└──────────────────────────────────────────────────────┘
↓ depende de
┌──────────────────────────────────────────────────────┐
│ Application Layer │
│ (Services - Lógica de Negocio) │
│ │
│ ISecurityService ← SecurityService │
│ IInventoryService ← InventoryService │
│ ICustomerService ← CustomerService │
│ IInvoiceService ← InvoiceService │
│ │
│ + DTOs (Request/Response) │
└──────────────────────────────────────────────────────┘
↓ depende de
┌──────────────────────────────────────────────────────┐
│ Domain Layer │
│ (Entidades - Reglas de Negocio) │
│ │
│ Entities: User, Role, Product, Customer, Invoice │
│ Interfaces: IUserRepository, IProductRepository │
└──────────────────────────────────────────────────────┘
↓ implementado por
┌──────────────────────────────────────────────────────┐
│ Infrastructure Layer │
│ (Implementaciones - EF Core + SQL) │
│ │
│ Repositories: UserRepository, ProductRepository │
│ DbContext: ApplicationDbContext │
│ Configurations: Fluent API mappings │
└──────────────────────────────────────────────────────┘
1. HTTP Request (ej: POST /api/Sales/invoices)
2. SalesController recibe el request
3. Controller llama a IInvoiceService
4. InvoiceService (implementación) ejecuta lógica de negocio
5. Service usa IRepository para acceso a datos
6. Repository usa EF Core para consultar SQL Server
7. Response regresa por el mismo camino (inverso)
✅ Single Responsibility Principle (SRP)
- Cada servicio tiene una única responsabilidad (CustomerService, InvoiceService, etc.)
- Cada repositorio maneja una sola entidad
✅ Open/Closed Principle (OCP)
- Extensible mediante nuevas implementaciones de servicios
- Cerrado a modificación en componentes existentes
✅ Liskov Substitution Principle (LSP)
- Cualquier implementación de
IServicepuede sustituir a otra - Todos los repositorios implementan
IRepository<T>
✅ Interface Segregation Principle (ISP)
- Interfaces pequeñas y específicas por dominio
ICustomerService,IInvoiceServiceseparados (no una interfaz gorda)
✅ Dependency Inversion Principle (DIP)
- Controllers dependen de abstracciones (
IService) - Services dependen de abstracciones (
IRepository) - No hay dependencias directas de implementaciones concretas
PoliMarket-Backend/
│
├── Application/ # Capa de Aplicación
│ ├── Common/
│ │ ├── DependencyInjection.cs # Registro de servicios
│ │ └── Interfaces/
│ │ └── IApplicationDbContext.cs
│ │
│ ├── Inventory/ # Módulo Inventario
│ │ ├── DTOs/
│ │ │ ├── ProductResponse.cs
│ │ │ ├── CheckStockRequest.cs
│ │ │ └── CheckStockResponse.cs
│ │ └── Services/
│ │ ├── IInventoryService.cs
│ │ └── InventoryService.cs
│ │
│ ├── Sales/ # Módulo Ventas
│ │ ├── DTOs/
│ │ │ ├── CustomerResponse.cs
│ │ │ ├── InvoiceResponse.cs
│ │ │ └── CreateInvoiceRequest.cs
│ │ └── Services/
│ │ ├── ICustomerService.cs
│ │ ├── CustomerService.cs
│ │ ├── IInvoiceService.cs
│ │ └── InvoiceService.cs
│ │
│ └── Security/ # Módulo Seguridad
│ ├── DTOs/
│ │ ├── LoginRequest.cs
│ │ ├── LoginResponse.cs
│ │ └── UserResponse.cs
│ └── Services/
│ ├── ISecurityService.cs
│ ├── SecurityService.cs
│ └── IPasswordHasher.cs
│
├── Domain/ # Capa de Dominio
│ ├── Entities/
│ │ ├── BaseEntity.cs # Entidad base (Id, CreatedAt, UpdatedAt)
│ │ ├── Inventory/
│ │ │ ├── Product.cs
│ │ │ ├── Supplier.cs
│ │ │ ├── InventoryMovement.cs
│ │ │ └── StockAlert.cs
│ │ ├── Sales/
│ │ │ ├── Customer.cs
│ │ │ ├── Invoice.cs
│ │ │ └── InvoiceDetail.cs
│ │ ├── Security/
│ │ │ ├── User.cs
│ │ │ └── Rol.cs
│ │ └── Logistics/
│ │ └── DeliveryOrder.cs
│ │
│ └── Repositories/ # Interfaces de repositorios
│ ├── IRepository.cs # Repositorio genérico
│ ├── IUserRepository.cs
│ ├── IProductRepository.cs
│ ├── ICustomerRepository.cs
│ └── IInvoiceRepository.cs
│
├── Infrastructure/ # Capa de Infraestructura
│ ├── Persistence/
│ │ ├── ApplicationDbContext.cs
│ │ ├── Configurations/ # Fluent API
│ │ │ ├── Inventory/
│ │ │ ├── Sales/
│ │ │ ├── Security/
│ │ │ └── Logistics/
│ │ └── Migrations/ # EF Core Migrations
│ │
│ ├── Repositories/ # Implementaciones
│ │ ├── BaseRepository.cs
│ │ ├── Inventory/
│ │ │ ├── ProductRepository.cs
│ │ │ └── InventoryMovementRepository.cs
│ │ ├── Sales/
│ │ │ ├── CustomerRepository.cs
│ │ │ └── InvoiceRepository.cs
│ │ └── Security/
│ │ ├── UserRepository.cs
│ │ └── RolRepository.cs
│ │
│ ├── Security/
│ │ └── PasswordHasher.cs # Hashing con SHA256
│ │
│ └── Common/
│ └── DependencyInjection.cs # Registro de infraestructura
│
├── Presentation/ # Capa de Presentación
│ └── Controllers/
│ ├── BaseApiController.cs # Controlador base
│ ├── SecurityController.cs # Endpoints de autenticación
│ ├── InventoryController.cs # Endpoints de inventario
│ ├── SalesController.cs # Endpoints de ventas
│ └── LogisticsController.cs # Endpoints de logística
│
├── Database/ # Scripts SQL
│ ├── SeedData.sql # Roles y usuarios iniciales
│ ├── SeedData_Inventory.sql # Productos y proveedores
│ └── SeedData_Sales.sql # Clientes de prueba
│
├── docs/ # Documentación
│ ├── Architecture/
│ │ └── MEDIATR_REMOVAL_SUMMARY.md
│ ├── Security/
│ │ └── README.md
│ ├── Inventory/
│ │ └── README.md
│ └── Sales/
│ └── README.md
│
├── Program.cs # Punto de entrada
├── appsettings.json # Configuración
└── PoliMarket-Backend.csproj # Proyecto .NET
- .NET 9 (Framework principal)
- ASP.NET Core Web API (REST API)
- Entity Framework Core 9.0 (ORM)
- SQL Server (Base de datos)
- Clean Architecture (separación de capas)
- SOLID Principles (diseño orientado a objetos)
- Service Layer Pattern (lógica de negocio)
- Repository Pattern (abstracción de datos)
- Dependency Injection (IoC Container)
- Unit of Work (transacciones)
- EF Core Migrations (gestión de esquema de BD)
- Fluent API (configuración de entidades)
- SHA256 (hashing de contraseñas)
- .NET 9 SDK o superior
- SQL Server (Express o superior)
- Visual Studio 2022 / VS Code / Rider
- SQL Server Management Studio (opcional)
git clone https://github.com/tu-usuario/PoliMarket-Backend.git
cd PoliMarket-BackendEdita appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=PoliMarketDb;Integrated Security=true;TrustServerCertificate=true;MultipleActiveResultSets=true;"
}
}dotnet ef database updateEsto ejecutará las migraciones y creará la base de datos PoliMarketDb con todas las tablas.
# Usuarios y roles
sqlcmd -S .\SQLEXPRESS -d PoliMarketDb -i Database\SeedData.sql
# Productos y proveedores
sqlcmd -S .\SQLEXPRESS -d PoliMarketDb -i Database\SeedData_Inventory.sql
# Clientes
sqlcmd -S .\SQLEXPRESS -d PoliMarketDb -i Database\SeedData_Sales.sqldotnet runLa API estará disponible en:
- HTTP:
http://localhost:5289 - HTTPS:
https://localhost:7057
Si prefieres levantar la API y SQL Server en contenedores:
# Construir y levantar los servicios
docker compose up -d
# Ver logs
docker compose logs -f api- API:
http://localhost:8080 - Swagger:
http://localhost:8080/swagger - SQL Server:
localhost:1433(usuariosa, contraseña por defectoYourStrong@Passw0rd)
Las migraciones EF se ejecutan automáticamente al arrancar la API. Para usar otra contraseña de SQL Server, define la variable de entorno MSSQL_SA_PASSWORD antes de docker compose up.
Para cargar datos de prueba en la base de datos del contenedor, ejecuta los scripts en Database/ conectándote a localhost,1433 (por ejemplo con Azure Data Studio o sqlcmd).
# Login
curl -X POST http://localhost:5289/api/Security/login \
-H "Content-Type: application/json" \
-d '{"username": "jperez", "password": "password123"}'
# Listar productos
curl http://localhost:5289/api/Inventory/products
# Crear factura (con validación de stock)
curl -X POST http://localhost:5289/api/Sales/invoices \
-H "Content-Type: application/json" \
-d '{
"salesPersonId": 2,
"customerId": 1,
"details": [
{"productId": 1, "quantitySold": 2}
]
}'Navega a: http://localhost:5289/openapi (si está habilitado en desarrollo)
Responsabilidad: Autenticación y gestión de usuarios
Endpoints:
POST /api/Security/login- Iniciar sesiónGET /api/Security/users- Listar usuariosPOST /api/Security/users- Crear usuarioPUT /api/Security/users/{id}- Actualizar usuarioPOST /api/Security/users/{id}/revoke-access- Revocar accesoGET /api/Security/roles- Listar roles
Entidades:
User(usuarios/empleados)Rol(roles del sistema)
Características:
- ✅ Autenticación con usuario/contraseña
- ✅ Hashing de contraseñas (SHA256)
- ✅ Validación de usuarios activos
- ✅ Gestión de roles (Vendedor Activo, Administrador, etc.)
Responsabilidad: Gestión de productos y stock
Endpoints:
GET /api/Inventory/products- Listar productosGET /api/Inventory/products/{id}- Obtener productoGET /api/Inventory/products/{id}/stock- Consultar stock (RF03)POST /api/Inventory/products/check-stock- Validar disponibilidad (RF03)GET /api/Inventory/products/{id}/suppliers- Producto con proveedores
Entidades:
Product(productos del inventario)Supplier(proveedores)ProductSupplier(relación productos-proveedores)InventoryMovement(movimientos de stock)StockAlert(alertas de stock bajo)
Características:
- ✅ RF03: Consulta en tiempo real de disponibilidad
- CA 3.1: Visualización de stock exacto
- CA 3.2: Validación positiva (stock suficiente)
- CA 3.3: Validación negativa con mensaje claro
- CA 3.4: Latencia < 1 segundo
- ✅ Trazabilidad de movimientos de inventario
- ✅ Gestión de proveedores por producto
Responsabilidad: Gestión de clientes y facturación
Endpoints Clientes:
GET /api/Sales/customers- Listar clientesGET /api/Sales/customers/{id}- Obtener clientePOST /api/Sales/customers- Crear clientePUT /api/Sales/customers/{id}- Actualizar clienteDELETE /api/Sales/customers/{id}- Eliminar cliente
Endpoints Facturas:
GET /api/Sales/invoices- Listar facturasGET /api/Sales/invoices/{id}- Obtener facturaPOST /api/Sales/invoices- ⭐ Crear factura (RF03 + RF04)
Entidades:
Customer(clientes)Invoice(facturas)InvoiceDetail(detalles de factura)
Características:
- ✅ CRUD completo de clientes
- ✅ Validación de emails únicos
- ✅ RF03 + RF04: Facturación con validación e integración de stock
- Valida stock en tiempo real antes de venta
- Descuenta stock automáticamente
- Transaccionalidad completa (rollback si falla)
- Registra movimientos de inventario
- ✅ Validación de vendedor activo (RF01)
- ✅ Protección de integridad referencial
Responsabilidad: Gestión de órdenes de entrega
Endpoints:
GET /api/Logistics/delivery-orders- Listar órdenes de entregaGET /api/Logistics/delivery-orders/{id}- Obtener orden por IDGET /api/Logistics/delivery-orders/pending- Órdenes pendientes (RF05 CA 5.3)POST /api/Logistics/delivery-orders/generate/{invoiceId}- Generar orden manual
Entidades:
DeliveryOrder(órdenes de entrega)
Características:
- ✅ RF05: Generación Automática de Órdenes de Entrega
- CA 5.1: Creación automática con estado "Pending"
- CA 5.2: Incluye datos del cliente, dirección y productos
- CA 5.3: Panel de control dedicado sin intervención manual
- ✅ Integración automática con módulo Sales
- ✅ Consulta de órdenes pendientes
Cuando se crea una factura:
// 1. Sales valida que el vendedor esté activo
var salesPerson = await _userRepository.GetByIdAsync(request.SalesPersonId);
if (!salesPerson.IsActive)
throw new InvalidOperationException("Vendedor no activo");Al crear una factura:
// 2. Sales consulta stock disponible (RF03)
foreach (var detail in request.Details)
{
var product = await _productRepository.GetByIdAsync(detail.ProductId);
if (detail.QuantitySold > product.QuantityAvailable)
throw new InvalidOperationException("Stock insuficiente");
}
// 3. Sales reduce stock automáticamente (RF04)
using var transaction = await _context.Database.BeginTransactionAsync();
product.QuantityAvailable -= detail.QuantitySold;
await _productRepository.UpdateAsync(product);
// 4. Sales registra movimiento de inventario (RF04)
var movement = new InventoryMovement
{
ProductId = detail.ProductId,
MovementType = 'O', // Output
Quantity = detail.QuantitySold,
EntityName = "Invoice",
EntityId = invoice.Id
};
await _inventoryMovementRepository.AddAsync(movement);
await transaction.CommitAsync();Una vez completada la venta:
// 5. Sales genera automáticamente orden de entrega (RF05)
await transaction.CommitAsync(); // Confirmar venta primero
// RF05 CA 5.1, 5.2, 5.3: Generar orden con datos completos
await _deliveryOrderService.GenerateDeliveryOrderAsync(invoiceId);
// La orden se crea con:
// - Estado: "Pending" (CA 5.1)
// - Datos: Cliente, Dirección, Productos, ID de Venta (CA 5.2)
// - Visible en panel de Entregas sin intervención manual (CA 5.3)El sistema utiliza 4 esquemas para separación lógica:
| Esquema | Descripción | Tablas |
|---|---|---|
Security |
Usuarios y roles | Users, Roles |
Inventory |
Productos y stock | Products, Suppliers, ProductSuppliers, InventoryMovements, StockAlerts |
Sales |
Ventas y clientes | Customers, Invoices, InvoiceDetails |
Logistics |
Logística | DeliveryOrders |
Security.Users (Vendedores)
↓ 1:N
Sales.Invoices ← N:1 → Sales.Customers
↓ 1:N
Sales.InvoiceDetails → N:1 → Inventory.Products
↓ 1:N
Inventory.InventoryMovements
# Ver migraciones aplicadas
dotnet ef migrations list
# Crear nueva migración
dotnet ef migrations add NombreMigracion
# Aplicar migraciones
dotnet ef database update
# Revertir a migración específica
dotnet ef database update MigracionAnteriorVer guías de testing en cada módulo:
-
Login y Autenticación
curl -X POST http://localhost:5289/api/Security/login \ -H "Content-Type: application/json" \ -d '{"username": "jperez", "password": "password123"}'
-
Consultar Productos
curl http://localhost:5289/api/Inventory/products
-
Validar Stock
curl -X POST http://localhost:5289/api/Inventory/products/check-stock \ -H "Content-Type: application/json" \ -d '{"productId": 1, "quantityRequested": 5}'
-
Crear Factura (Integración RF03 + RF04)
curl -X POST http://localhost:5289/api/Sales/invoices \ -H "Content-Type: application/json" \ -d '{ "salesPersonId": 2, "customerId": 1, "details": [ {"productId": 1, "quantitySold": 2}, {"productId": 3, "quantitySold": 5} ] }'
-
Verificar Movimientos de Inventario
SELECT * FROM Inventory.InventoryMovements WHERE EntityName = 'Invoice' ORDER BY MovementDate DESC;
-
Verificar Orden de Entrega Generada (RF05)
curl http://localhost:5289/api/Logistics/delivery-orders/pending
| RF | Descripción | Estado | Módulo | Criterios |
|---|---|---|---|---|
| RF01 | Gestión Centralizada de Autorizaciones | ✅ 100% | Security | 2/2 CA |
| RF02 | Inicio de Sesión de Usuarios | ✅ 100% | Security | 4/4 CA |
| RF03 | Consulta en Tiempo Real de Disponibilidad | ✅ 100% | Inventory + Sales | 4/4 CA |
| RF04 | Registro Automatizado de Salida de Stock | ✅ 100% | Sales + Inventory | 3/3 CA |
| RF05 | Generación Automática de Órdenes | ✅ 100% | Logistics | 3/3 CA |
| Módulo | Estado | Endpoints | Tests | Documentación |
|---|---|---|---|---|
| Security | ✅ Completo | 6 | ✅ | ✅ |
| Inventory | ✅ Completo | 5 | ✅ | ✅ |
| Sales | ✅ Completo | 8 | ✅ | ✅ |
| Logistics | ✅ Completo | 4 | ✅ | ✅ |
- Líneas de código: ~7,200
- Archivos C#: ~88
- Controladores: 4
- Servicios: 5
- Repositorios: 9
- Entidades: 11
- Compilación: ✅ 0 errores, 0 warnings
- Cobertura SOLID: ✅ 100%
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=PoliMarketDb;Integrated Security=true;TrustServerCertificate=true;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Information"
}
},
"AllowedHosts": "*"
}- Connection String: Ajustar según tu instancia de SQL Server
- Entity Framework Logging: Nivel
Informationpara ver queries SQL - HTTPS: Puerto 7057 (desarrollo)
- HTTP: Puerto 5289 (desarrollo)
- [✅] RF05: Generación Automática de Órdenes de Entrega
- [✅] Módulo Logistics completo
- [✅] Integración automática Sales → Logistics
- Implementar JWT para autenticación stateless
- Agregar middleware de manejo de excepciones global
- Implementar logging con Serilog
- Actualización de estados de órdenes de entrega
- Tests unitarios (xUnit)
- Tests de integración
- Documentación OpenAPI/Swagger mejorada
- CI/CD con GitHub Actions
- Implementar cache con Redis
- Agregar rate limiting
- Implementar CORS configurado
- Dashboard de métricas
- Migrar a BCrypt para hashing de contraseñas
- Implementar refresh tokens
- Agregar versionado de API
- Implementar pagination en endpoints de listado
- Agregar filtros y búsqueda avanzada
- Arquitectura - Eliminación de MediatR
- Módulo Security - Guía Completa
- Módulo Inventory - Guía Completa
- Módulo Sales - Guía Completa
- Módulo Logistics - Guía Completa
- Database Setup
- Seguir convenciones de C# y .NET
- Aplicar principios SOLID
- Documentar métodos públicos con
<summary> - Usar nombres descriptivos en español para entidades de negocio
- Mantener arquitectura Clean Architecture
- Fork el repositorio
- Crear una rama feature (
git checkout -b feature/NuevaFuncionalidad) - Commit cambios (
git commit -m 'Add: Nueva funcionalidad') - Push a la rama (
git push origin feature/NuevaFuncionalidad) - Abrir un Pull Request
- Backend Lead: [Tu Nombre]
- Arquitectura: [Nombre]
- Database: [Nombre]
Este proyecto es privado y propiedad de PoliMarket.
Para preguntas o issues:
- Email: soporte@polimarket.com
- Issues: GitHub Issues (si aplica)
- Equipo de desarrollo PoliMarket
- Comunidad .NET
- Microsoft por las herramientas y frameworks
Última actualización: Noviembre 2024
Versión: 1.1.0
Estado: ✅ Producción-Ready para RF01-RF05 (Todos los requisitos funcionales completados)