Solución mínima basada en microservicios para la gestión de clientes, productos y pedidos en un entorno B2B.
Nota: La consigna original menciona MySQL y archivos
db/schema.sql/db/seed.sql. Esta implementación fue adaptada a PostgreSQL, y la creación de tablas se realiza de forma programática desde Node.js al iniciar los servicios, manteniendo la estructura general del proyecto.
/customer-api
/orders-api
/lambda-orchestrator
/db
docker-compose.yml
README.md
- Node.js + Express
- PostgreSQL
- Docker & Docker Compose
- JSON Web Token (JWT)
- Serverless Framework (orquestador)
- SQL parametrizado con validación de datos
| Servicio | URL |
|---|---|
| Customers API | http://localhost:3001 |
| Orders API | http://localhost:3002 |
| PostgreSQL | localhost:5432 |
| Lambda Orchestrator | http://localhost:3003 (según configuración serverless-offline) |
- Docker
- Docker Compose
- Node.js 22 o compatible
- npm
Cada microservicio requiere un archivo .env basado en su .env.example.
PORT=3001
DB_HOST=postgres
DB_PORT=5432
DB_NAME=backoffice_b2b
DB_USER=postgres
DB_PASSWORD=postgres
JWT_SECRET=super-secret-jwt
SERVICE_TOKEN=internal-service-tokenPORT=3002
DB_HOST=postgres
DB_PORT=5432
DB_NAME=backoffice_b2b
DB_USER=postgres
DB_PASSWORD=postgres
JWT_SECRET=super-secret-jwt
SERVICE_TOKEN=internal-service-token
CUSTOMERS_API_BASE=http://customers-api:3001CUSTOMERS_API_BASE=http://localhost:3001
ORDERS_API_BASE=http://localhost:3002
SERVICE_TOKEN=internal-service-tokengit clone <URL_DEL_REPOSITORIO>
cd <NOMBRE_DEL_PROYECTO>Copiar los .env.example en cada servicio:
cp customers-api/.env.example customers-api/.env
cp orders-api/.env.example orders-api/.env
cp lambda-orchestrator/.env.example lambda-orchestrator/.envdocker compose builddocker compose up -ddocker psVerificar health de las APIs:
- Customers API → http://localhost:3001/health
- Orders API → http://localhost:3002/health
docker compose down
# Para eliminar también los volúmenes:
docker compose down -vPostgreSQL corre en Docker a través del servicio postgres definido en docker-compose.yml. Al arrancar, cada API se conecta y crea sus tablas automáticamente mediante código Node.js si no existen — sin necesidad de migraciones manuales.
| Método | Ruta | Descripción |
|---|---|---|
| POST | /auth/login |
Obtener token JWT |
| GET | /health |
Health check |
| POST | /customers |
Crear cliente |
| GET | /customers |
Listar clientes (con búsqueda) |
| GET | /customers/:id |
Obtener cliente por ID |
| PUT | /customers/:id |
Actualizar cliente |
| DELETE | /customers/:id |
Eliminar cliente |
| GET | /internal/customers/:id |
Uso interno entre servicios |
| Método | Ruta | Descripción |
|---|---|---|
| POST | /auth/login |
Obtener token JWT |
| GET | /health |
Health check |
| POST | /products |
Crear producto |
| GET | /products |
Listar productos |
| GET | /products/:id |
Obtener producto por ID |
| PATCH | /products/:id |
Actualizar producto |
| POST | /orders |
Crear orden |
| GET | /orders |
Listar órdenes |
| GET | /orders/:id |
Obtener orden por ID |
| POST | /orders/:id/confirm |
Confirmar orden (idempotente) |
| POST | /orders/:id/cancel |
Cancelar orden |
- Llamar a
POST /auth/login - Obtener el token
- Incluirlo en el header:
Authorization: Bearer <token>
Authorization: Bearer internal-service-token
curl -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin"}'curl -X POST http://localhost:3001/customers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN" \
-d '{"name":"ACME Corp","email":"ops@acme.com","phone":"0999999999"}'curl -X GET http://localhost:3001/customers/1 \
-H "Authorization: Bearer TU_TOKEN"curl -X GET "http://localhost:3001/customers?search=acme&limit=10" \
-H "Authorization: Bearer TU_TOKEN"curl -X POST http://localhost:3002/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_ORDERS" \
-d '{"sku":"SKU-001","name":"Laptop Dell","price_cents":129900,"stock":10}'curl -X POST http://localhost:3002/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_ORDERS" \
-d '{"customer_id":1,"items":[{"product_id":1,"qty":2}]}'curl -X POST http://localhost:3002/orders/1/confirm \
-H "Authorization: Bearer TU_TOKEN_ORDERS" \
-H "X-Idempotency-Key: abc-123"curl -X POST http://localhost:3002/orders/1/cancel \
-H "Authorization: Bearer TU_TOKEN_ORDERS"Orquestador invocable por HTTP que valida el cliente, crea la orden y la confirma, devolviendo una respuesta consolidada.
cd lambda-orchestrator
npm install
npm run devPOST /orchestrator/create-and-confirm-order
Body:
{
"customer_id": 1,
"items": [
{ "product_id": 2, "qty": 3 }
],
"idempotency_key": "abc-123",
"correlation_id": "req-789"
}- Cada microservicio tiene su propio
Dockerfile. - Usar
DB_HOST=postgresdentro de contenedores (nolocalhost). - No incluir
node_modulesen el repositorio. - Usar
.dockerignoreen cada servicio. - Usar
package-lock.jsonpara instalaciones reproducibles.
| Problema | Solución |
|---|---|
| Error de conexión a DB | Verificar que PostgreSQL esté arriba y que DB_HOST=postgres |
| API falla al iniciar | Revisar logs: docker compose logs customers-api |
| Puerto ocupado | Cambiar puerto en docker-compose.yml o liberar el puerto |
| Token inválido | Verificar JWT_SECRET y el header Authorization |
| Error entre servicios | Verificar que SERVICE_TOKEN sea el mismo en ambos servicios |
- Customers API funcional
- Orders API funcional
- Levantamiento local con Docker Compose
- Validación de cliente desde Orders contra Customers
- Creación de órdenes con validación de stock
- Confirmación idempotente con
X-Idempotency-Key - Cancelación con restauración de stock
- Base de datos en contenedor Docker
- Estructura de monorepo
- Lambda Orchestrator completo
- Documentación OpenAPI
- Colección Postman / Insomnia
- Archivos
db/schema.sqlydb/seed.sqlcomo referencia documental - Despliegue en AWS