Skip to content

JDeat-S/StockFlow-API

Repository files navigation

StockFlow API

API REST profesional para gestión de inventario y punto de venta, pensada para pequeños y medianos negocios (PyMEs) como tiendas de abarrotes, ferreterías y misceláneas.

Construida con ASP.NET Core 8, Entity Framework Core (SQL Server), JWT con roles y arquitectura en capas.


El problema de negocio que resuelve

Una tienda de abarrotes o ferretería típica en México lleva su inventario en libretas o en Excel. Eso provoca tres problemas concretos:

  1. Ventas de productos que ya no hay — el vendedor no sabe el stock real al momento de cobrar.
  2. Quiebres de stock silenciosos — nadie se entera de que se acabó el producto estrella hasta que un cliente lo pide.
  3. Cero visibilidad del negocio — el dueño no sabe cuánto vale su inventario, qué productos se venden más, ni cuánto vendió la semana pasada.

StockFlow resuelve los tres:

  • Cada venta valida y descuenta stock automáticamente dentro de una transacción de base de datos: o se registra el ticket completo, o no se descuenta nada.
  • El endpoint de alertas lista los productos en o por debajo de su stock mínimo, con el faltante sugerido para resurtir.
  • Los reportes responden las preguntas del dueño: ventas por rango de fechas, top 10 de productos más vendidos y valor total del inventario (a costo y a precio de venta, con utilidad potencial).

Funcionalidad

Módulo Endpoints Acceso
Autenticación POST /api/auth/login Público
Productos CRUD completo en /api/productos Lectura: ambos roles · Escritura: Admin
Categorías CRUD completo en /api/categorias Lectura: ambos roles · Escritura: Admin
Proveedores CRUD en /api/proveedores Lectura: ambos roles · Escritura: Admin
Ventas POST /api/ventas (descuenta stock), consultas Registrar: Admin y Vendedor
Entradas de mercancía POST /api/entradas (aumenta stock), consultas Registrar: Admin
Alertas GET /api/alertas/stock-bajo Ambos roles
Reportes GET /api/reportes/ventas, /top-productos, /valor-inventario Ambos roles

Usuarios de demostración (creados por los datos semilla):

Usuario Contraseña Rol
admin Admin123! Admin
vendedor Vendedor123! Vendedor

Modelo de datos

erDiagram
    Categoria ||--o{ Producto : "contiene"
    Producto ||--o{ DetalleVenta : "se vende en"
    Producto ||--o{ DetalleEntrada : "se recibe en"
    Venta ||--|{ DetalleVenta : "incluye"
    EntradaMercancia ||--|{ DetalleEntrada : "incluye"
    Usuario ||--o{ Venta : "registra"
    Usuario ||--o{ EntradaMercancia : "registra"
    Proveedor ||--o{ EntradaMercancia : "surte"

    Categoria {
        int Id PK
        string Nombre UK
        string Descripcion
    }
    Producto {
        int Id PK
        string Nombre
        string Sku UK
        int CategoriaId FK
        decimal PrecioCompra
        decimal PrecioVenta
        int StockActual
        int StockMinimo
        bool Activo
        datetime FechaCreacion
    }
    Venta {
        int Id PK
        string Folio UK
        int UsuarioId FK
        datetime Fecha
        decimal Total
    }
    DetalleVenta {
        int Id PK
        int VentaId FK
        int ProductoId FK
        int Cantidad
        decimal PrecioUnitario
        decimal Subtotal
    }
    Proveedor {
        int Id PK
        string Nombre
        string Rfc
        string Telefono
        bool Activo
    }
    EntradaMercancia {
        int Id PK
        int ProveedorId FK
        int UsuarioId FK
        datetime Fecha
        decimal Total
        string Observaciones
    }
    DetalleEntrada {
        int Id PK
        int EntradaId FK
        int ProductoId FK
        int Cantidad
        decimal CostoUnitario
        decimal Subtotal
    }
    Usuario {
        int Id PK
        string NombreUsuario UK
        string NombreCompleto
        string PasswordHash
        string Rol
        bool Activo
    }
Loading

Documentación Swagger

Toda la documentación de endpoints está en español, con los usuarios demo visibles en la descripción y botón Authorize para el token JWT:

Endpoints de StockFlow API en Swagger

Instalación paso a paso

Requisitos

  • SDK de .NET 8
  • SQL Server: LocalDB (incluido con Visual Studio), SQL Server Express, o una instancia completa

Pasos

  1. Clonar el repositorio

    git clone https://github.com/JDeat-S/StockFlow-API.git
    cd StockFlow-API
  2. Verificar la cadena de conexión en src/StockFlow.Api/appsettings.json. Por defecto usa LocalDB:

    "ConnectionStrings": {
      "StockFlow": "Server=(localdb)\\MSSQLLocalDB;Database=StockFlowDb;Trusted_Connection=True;TrustServerCertificate=True"
    }

    Si usas SQL Server Express, cambia el servidor a .\SQLEXPRESS. Si usas una instancia con usuario y contraseña: Server=localhost;Database=StockFlowDb;User Id=sa;Password=TU_PASSWORD;TrustServerCertificate=True.

  3. Ejecutar la API

    dotnet run --project src/StockFlow.Api

    Al arrancar, la API aplica las migraciones automáticamente y, si la base está vacía, carga los datos semilla (36 productos de abarrotes y ferretería, ventas y una entrada de ejemplo). No se necesita ningún paso manual de base de datos.

  4. Abrir Swagger en la URL que indique la consola (ej. http://localhost:5188/swagger).

  5. Autenticarse: ejecutar POST /api/auth/login con admin / Admin123!, copiar el token de la respuesta, hacer clic en Authorize y pegarlo.

Ejecutar las pruebas

dotnet test

20 pruebas unitarias (xUnit + EF Core In-Memory) cubren la lógica de negocio: validación y descuento de stock, atomicidad de la venta, folios consecutivos, alertas y reportes.

Estructura del proyecto

src/StockFlow.Api/
├── Controllers/     # Capa HTTP: rutas, códigos de estado, autorización por rol
├── Services/        # Lógica de negocio (transacciones, validaciones de dominio)
├── Repositories/    # Acceso a datos: repositorio genérico + repos específicos
├── DTOs/            # Contratos de entrada/salida, separados de las entidades
├── Validators/      # Reglas FluentValidation por cada DTO de escritura
├── Middleware/      # Manejador global de errores con respuestas JSON consistentes
├── Models/          # Entidades de EF Core
├── Data/            # DbContext, migraciones y datos semilla
└── Helpers/         # Constantes de roles y excepciones de dominio
tests/StockFlow.Tests/   # Pruebas unitarias de los servicios

Formato de respuesta estándar

Todas las respuestas (éxito y error, incluidos 401/403 del middleware de autenticación) usan la misma envoltura:

{
  "exito": false,
  "mensaje": "Stock insuficiente para \"Refresco Coca-Cola 600 ml\" (SKU BEB-001): se solicitaron 9999 y solo hay 103.",
  "datos": null,
  "errores": null
}

Decisiones técnicas

  • Transacción explícita en ventas y entradas. VentaService.CrearAsync envuelve la validación de stock, el descuento y el alta del ticket en BeginTransactionAsync. Si cualquier renglón falla (producto inexistente, inactivo o sin stock), no se persiste nada. Una prueba unitaria (CrearVenta_UnRenglonSinStock_NoPersisteNada) verifica esa atomicidad.

  • El precio se copia al detalle al momento de la operación. DetalleVenta.PrecioUnitario y DetalleEntrada.CostoUnitario guardan el precio vigente al vender/comprar. Cambiar el precio de un producto después no altera tickets históricos ni reportes pasados.

  • El cliente nunca manda el precio. En POST /api/ventas solo se envían producto y cantidad; el precio se toma del catálogo en el servidor. Esto evita que un cliente malicioso registre ventas con precios alterados.

  • El stock no se edita directamente. PUT /api/productos/{id} no acepta stockActual: el stock solo cambia mediante ventas (resta) y entradas de mercancía (suma). Así todo movimiento de inventario queda auditado.

  • Borrado lógico de productos con historial. Eliminar un producto con ventas o entradas lo desactiva (Activo = false) en lugar de borrarlo, preservando la integridad referencial de tickets y reportes. Solo los productos sin movimientos se eliminan físicamente.

  • Folio legible por humanos (V-2026-00042) con consecutivo anual, separado del Id técnico — es lo que el dueño escribe en un ticket o busca cuando hay una aclaración.

  • Renglones duplicados se consolidan. Si el mismo producto llega dos veces en una venta, las cantidades se suman antes de validar stock; así no se puede burlar la validación dividiendo la cantidad.

  • Roles como constantes, no tabla. Con dos roles fijos (Admin, Vendedor), una tabla de roles sería sobre-ingeniería. Se usa PasswordHasher de ASP.NET Identity para el hash de contraseñas (PBKDF2) sin arrastrar todo el framework de Identity. El registro de ventas está permitido al rol Vendedor porque es la operación diaria del punto de venta; el resto de las escrituras (catálogo, entradas) requiere Admin.

  • Capas en carpetas dentro de un solo proyecto. Controllers → Services → Repositories demuestran la separación de responsabilidades sin la fricción de 4 proyectos; quien clona el repo lo compila y entiende en minutos. Los reportes (solo lectura, con agregaciones) consultan EF Core directamente con AsNoTracking y proyecciones — un patrón tipo CQRS-lite documentado en ReporteService.

  • Mensajes de error accionables. El error de stock insuficiente indica producto, SKU, cantidad solicitada y stock disponible. El login falla con el mismo mensaje para usuario inexistente y contraseña incorrecta (no se revela cuál falló).

  • Migraciones y seed automáticos al arrancar. Para un proyecto demo, eliminar pasos manuales de instalación vale más que el control fino de despliegue; en producción se ejecutarían las migraciones en el pipeline de CI/CD.

  • ⚠️ Nota de seguridad: la clave JWT vive en appsettings.json solo por tratarse de un proyecto de demostración. En producción debe ir en variables de entorno o un gestor de secretos (Azure Key Vault, AWS Secrets Manager), igual que la cadena de conexión.

Stack

Tecnología Uso
ASP.NET Core 8 Web API Framework principal
Entity Framework Core 8 + SQL Server ORM, Code First con migraciones
JWT Bearer Autenticación con roles
FluentValidation Validación declarativa de DTOs
Swashbuckle (Swagger) Documentación OpenAPI en español
xUnit + EF Core In-Memory Pruebas unitarias

About

API REST de inventario y punto de venta para PyMEs - ASP.NET Core 8, EF Core, JWT, SQL Server

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages