Desplegando una API de inventario Lean y DDD en Laravel 12

Construir una API en Laravel 12 y PHP 8.4 que respete principios de domain driven design y clean architecture puede parecer un malabarismo entre mantener el dominio puro, ofrecer una capa HTTP amigable y conectar las dependencias de infraestructura sin contaminar la lógica de negocio. En este artículo explico cómo implementamos una funcionalidad de Inventario para registrar y obtener items siguiendo una arquitectura en cuatro capas: Domain, Application, Infrastructure e Interfaces HTTP, con endpoints protegidos por Sanctum, políticas, idempotencia para escrituras, limitación de tasa y pruebas con Pest.
Dominio: entidades, value objects y políticas. El objetivo es expresar el lenguaje ubicuo y las reglas sin introducir accidentalmente dependencias de Laravel. En app/Domain/Inventory se ubican piezas clave: el aggregate root InventoryItem que valida invariantes como nombre no vacío, stock no negativo y cantidad cero cuando está descontinuado. Value objects como Sku y Price encapsulan formato, normalización y comparación para que el resto del código nunca manipule strings crudos. Un enum InventoryItemStatus evita estados stringly typed. La interfaz InventoryItemRepositoryInterface devuelve entidades de dominio o PaginatedInventoryItems, y las excepciones de dominio como InventoryItemNotFound, DuplicateSkuException o IdempotencyConflictException unifican la semántica de fallo. Mantener el árbol de dominio sin framework permite que las pruebas se lean como reglas de negocio y sean muy rápidas.
Capa de aplicación: orquestación y DTOs. Aquí se coordinan casos de uso con mínimo conocimiento sobre la entrega o el almacenamiento. Creamos CreateInventoryItemCommand como DTO de entrada inmutable, RegisterInventoryItemResult e InventoryItemData como DTOs serializables de salida para evitar problemas de lazy loading. El caso de uso RegisterInventoryItem orquesta validaciones, llamadas al repositorio, comprobaciones de idempotencia y persiste dentro de una transacción. Se apoyó en contratos como ClockInterface, TransactionManagerInterface e IdempotencyServiceInterface para poder cambiar implementaciones de infraestructura sin tocar la lógica de negocio.
Infraestructura: adaptadores Laravel. La capa de infraestructura proporciona implementaciones concretas sin filtrar Eloquent hacia arriba. InventoryItemModel es un modelo Eloquent con factory personalizada. InventoryItemRepository transforma modelos a entidades de dominio, maneja paginación con filtros y ordenamientos controlados por el usuario y evita llamadas peligrosas como Model::all. Implementaciones como DatabaseTransactionManager, SystemClock y DatabaseIdempotencyService satisfacen los contratos definidos por la capa de aplicación. Las bindings en AppServiceProvider conectan interfaces con implementaciones concretas para mantener inversión de dependencias.
Interfaces y HTTP: requests, controllers, policies y rutas. El objetivo es mantener controladores delgados, validar temprano, mapear excepciones de dominio a códigos HTTP y proteger la API. StoreInventoryItemRequest valida, calcula un hash SHA256 del payload y exige el encabezado Idempotency-Key, además de autorizar con InventoryItemPolicy. FilterInventoryItemsRequest unifica parámetros de búsqueda, filtros, orden y paginación. InventoryItemController adapta peticiones HTTP a comandos de aplicación y devuelve recursos serializados. Un middleware o renderizado global de excepciones transforma excepciones de dominio en respuestas JSON con los códigos adecuados, por ejemplo 422, 404 o 409. Las políticas usan habilidades de Sanctum como inventory:read e inventory:write y las rutas registran throttling y middleware de autenticación.
Autenticación, políticas y rate limiting. Todas las rutas usan auth:sanctum y el modelo User emplea HasApiTokens. En AppServiceProvider se registra un rate limiter específico para inventory-items y se asocian modelos y políticas. En pruebas de integración se utiliza Sanctum::actingAs con las habilidades correctas para asegurar que incluso en tests la política aplica y se devuelve 403 cuando falta inventory:write.
Esquema de base de datos y seeders. Utilizamos dos migraciones principales: inventory_items con UUID como primary key, SKU indexado, columnas para currency y amount, status y timestamps; e idempotency_keys para almacenar usuario, clave, request_hash y respuesta para poder replay o detectar conflictos de idempotencia. Una factory y un seeder facilitan poblar datos de prueba y acelerar desarrollo.
Pruebas con Pest. Pest mantiene las pruebas concisas. Los tests unitarios se centran en value objects como Sku y Price y en el caso de uso RegisterInventoryItem, incluyendo pruebas de idempotencia y detección de SKU duplicado. Los tests funcionales usan RefreshDatabase, autentican con Sanctum y verifican escenarios: registro exitoso devuelve 201 y cabecera Idempotent-Replay false, reintento con la misma idempotency key retorna 200 y Idempotent-Replay true, errores de validación generan 422, duplicados 409 y solicitar un ID faltante devuelve 404 por la excepción de dominio mapeada.
Lecciones aprendidas y siguientes pasos. Delimitar el dominio facilita pruebas y refactorizaciones. Preferir contratos frente a facades en la capa de aplicación permite probar casos de uso sin mockear el framework. Manejar excepciones de dominio en el borde mantiene controladores limpios. La idempotencia justifica el coste de una tabla adicional para evitar duplicados en reintentos de clientes móviles o web. Futuras mejoras contemplan eventos de dominio como InventoryItemRegistered, endpoints PATCH para ajuste de stock con locking transaccional, migrar idempotencia a Redis para alto tráfico o añadir modelos de lectura CQRS o caching para listados.
En Q2BSTUDIO aplicamos estos mismos principios en proyectos reales de software a medida y desarrollo de aplicaciones a medida para clientes que necesitan soluciones robustas, seguras y escalables. Ofrecemos experiencia en inteligencia artificial, ia para empresas y agentes IA para automatizar tareas y mejorar decisiones. Si su proyecto requiere un sistema a medida con integración cloud y seguridad, podemos ayudarle a diseñar la arquitectura y la implementación.
Además de desarrollo, en Q2BSTUDIO cubrimos servicios cloud aws y azure y ciberseguridad para proteger sus aplicaciones. Si busca migrar o desplegar en la nube visite nuestra página de servicios cloud Servicios cloud AWS y Azure y si quiere soluciones de IA para su negocio consulte Inteligencia artificial para empresas. También ofrecemos servicios de inteligencia de negocio y power bi para convertir datos en insights accionables.
Palabras clave relevantes: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA, power bi. Si desea que adaptemos este patrón a su dominio de negocio o que desarrollemos una API de inventario o cualquier solución a medida, en Q2BSTUDIO somos especialistas en desarrollo, seguridad y despliegues cloud listos para llevar su producto al siguiente nivel.
Comentarios