📚 Unidad CIERRE-BUSINESS · Cierre Fase I — Business (sin Auth) — capa 🧠 APRENDER
🛠 Construir este bloque → · ✅ Condiciones de cierre (GATE) · 📝 Evaluación
Capa Página Para qué 🧠 Aprender esta página comprender, explicar y relacionar 🛠 Construir Cierre Fase I — Business (sin Auth) ejecutar, programar y verificar ✅ GATE Cierre de la unidad condición para pasar al bloque siguiente
Mapa de correspondencias. Cada fila enlaza el mismo tema en las dos capas de la unidad; los enlaces apuntan a secciones reales del material (anclas de MkDocs, sin acentos).
| Tema | 🧠 Aprender (esta página) | 🛠 Construir (ISS técnico) |
|---|---|---|
| Ruta y ficha de la unidad | Ruta de aprendizaje · Ficha del ISS | Contenido de la unidad |
| Mapas y estructura | Mapa mental · Mapa del backend · Árbol de archivos | Contenido de la unidad |
| Recorrido y comandos | Comandos explicados · Recorrido paso a paso | Contenido de la unidad |
| Diagnóstico | Diagnóstico | Criterios de aceptación |
| Evaluación y cierre | Criterios · Evaluación · GATE | Condiciones de cierre · Cierre |
🎬 Video explicativo
Recorrido audiovisual de la unidad. Este video audita la fase de negocio, de ISS-03 a ISS-08. No hay código nuevo. El orden de siembra es clientes, tipos, productos, ventas y detalle.
GET /api/clientessin token debe responder 200.
3:43 · narración en español · subtítulos activables desde el reproductor.
CIERRE-BUSINESS — Cuaderno de aprendizaje visual
Tema
Cierre de la Fase I — Business: la definición de terminado (DoD) del laboratorio sin autenticación y la verificación integral de las cinco features de negocio.
Fuente técnica autoritativa
| Archivo fuente | ../manual/10-cierre-business.md |
| Estado | Solo lectura — este cuaderno no modifica el documento de cierre |
| Alcance | 162 líneas: DoD de la Fase I, norma de nombres, cómo repetir el patrón, referencia rápida de paquetes y fuentes |
Este cuaderno es una capa pedagógica sobre ese archivo: el documento de cierre manda y aquí solo se explica cómo comprobar que la Fase I quedó cerrada. Todo su contenido técnico (checklist, normas, versiones) se reproduce íntegro y verbatim en la sección Recorrido del ISS, paso a paso.
A diferencia de un ISS de construcción, este documento es un instrumento de verificación: no escribe código nuevo, audita el que ya existe.
Pregunta que responde: ¿qué documento exacto define el final de la Fase I y qué alcance tiene?
Regla del ISS
Objetivo: cerrar la Fase I del laboratorio con el negocio completo y verificable. Bloqueado por: ISS-08 — Feature Sale + ProductSale.
La condición de cierre que exige el propio documento es el DoD del laboratorio (business SIN AUTH). Se cierra la fase solo si se cumplen, a la vez:
- Existen las 5 features (
clients,product-types,products,sales,product-sales), cada una con sus 4 capas y su DTO. - Existen las 5 tablas y responden las 5 familias de API, además de los seeders y Swagger.
- Ninguna ruta de negocio está protegida: la Fase I es deliberadamente SIN AUTH.
npx tsc --noEmittermina sin errores.
No hay criterio "extra": si el checklist del DoD está en verde, la fase está cerrada aunque todavía no exista seguridad. Eso llega en la Fase II.
Cómo leer este cuaderno
Cada concepto se presenta tres veces, desde tres ángulos distintos:
CONCEPTO
│
┌───────────┼───────────┐
▼ ▼ ▼
EXPLICACIÓN CÓDIGO VISUAL
│ │ │
¿qué es? ¿dónde está? ¿cómo lo
¿por qué? ¿qué hace? visualizo?
¿para qué? ¿cómo opera? ¿con qué
se relaciona?
Pregunta que responde: ¿cómo está organizado este cuaderno y qué espero encontrar en cada parte?
Un cuaderno de cierre cambia el acento: aquí el «código» que manda no es el que tú escribes, sino el código que auditas. Seis componentes guían esa auditoría:
| Componente | Dónde vive | Para qué sirve |
|---|---|---|
| Texto | todas las secciones | entender el por qué del cierre |
| Código | Recorrido del ISS |
ver el qué exacto que se audita |
| Diagramas | Mapa mental, Mapa del backend, Árbol de archivos, Flujos |
ver el cómo se conecta la fase |
| Preguntas | Evaluación y bajo cada diagrama |
comprobar que entendiste |
| Matriz de pruebas | La matriz de pruebas de la fase |
ejecutar y comprobar |
| GATE | GATE |
saber si puedes pasar a la Fase II |
Ruta de aprendizaje
Esta ruta es específica del cierre: primero se repasa lo construido, luego se prepara la matriz de pruebas, después se ejecuta y, por último, se audita el cierre.
Repaso de lo construido (5 features → 4 capas → 5 tablas)
↓
Norma de nombres y convenciones (carpeta, clase, tabla, FK)
↓
Matriz de pruebas de la fase (qué caso por cada ruta)
↓
Ejecución (tsc, seeders, servidor, Swagger)
↓
Auditoría de cierre (DoD completo en verde)
↓
GATE Fase I
Pregunta que responde: ¿cuál es el camino ordenado para dar por cerrada la Fase I?
Fíjate en lo que no aparece: no hay «crear feature», ni «escribir DTO», ni «configurar Swagger». Todo eso ya se hizo entre ISS-03 y ISS-08. Aquí solo se verifica.
Índice
- Ficha del ISS
- Mapa mental del ISS
- Mapa del backend
- Árbol de archivos
- Flujos
- Comandos explicados
- La matriz de pruebas de la fase
- Recorrido del ISS, paso a paso
- Diagnóstico
- Conexión con el resto del curso
- Glosario
- Criterios de aceptación
- Evaluación
- GATE
Ficha del ISS
| Campo | Valor |
|---|---|
| ISS | CIERRE Fase I — Business |
| Título | Cierre del laboratorio (business SIN AUTH) |
| Objetivo | Verificar que la Fase I queda completa: 5 features, 5 tablas, APIs, seeders y Swagger, todo SIN AUTH y con npx tsc --noEmit en verde |
| Fase | Fase I — Business (cierre) |
| Tecnología principal | Express 5 + TypeScript + Sequelize (arquitectura por features) |
| Depende de | ISS-08 — Feature Sale + ProductSale |
| Habilita | ISS-09 — Base de seguridad y modelos Auth |
| Archivos creados | Ninguno (documento de cierre: no escribe código) |
| Archivos parcheados | Ninguno |
| Componentes incorporados | Ninguno: se auditan los componentes de ISS-03 a ISS-08 |
| Verificación principal | npx tsc --noEmit sin errores + recorrido de las 5 familias de API y de Swagger |
| Resultado esperado | 5 features con sus 4 capas y DTO, 5 tablas, SeedersRunner, Swagger /api/docs, todas las rutas SIN AUTH |
| GATE | El checklist del DoD (business SIN AUTH) completo en verde |
Qué implementamos AHORA
Nada de código nuevo. Este cierre consolida y verifica la Fase I: comprueba que las cinco features siguen el recorrido obligatorio HTTP → Controller → Service → Repository → Model → Sequelize → BD, que la norma de nombres se respeta y que el negocio responde de punta a punta sin ninguna capa de seguridad.
Qué todavía NO implementamos
Este es el punto donde más fácil es confundirse: el negocio está cerrado, pero la seguridad todavía no existe.
| No se implementa aquí | Llega en |
|---|---|
Capa de seguridad base (JWT HS256, bcrypt 12, AppError, sendError, resource-match) |
ISS-09 |
Feature users (hash, cambio de contraseña, permisos efectivos) |
ISS-10 |
Features roles y resources (catálogo de 58 recursos) |
ISS-11 |
role_users y resource_roles (la matriz RBAC) |
ISS-12 |
Middlewares authenticate / authorize sobre las rutas de negocio |
ISS-13 |
refresh_tokens (hash SHA-256, rotación, detección de reúso) |
ISS-14 |
Feature session (login / refresh / logout / perfil) |
ISS-15 |
Ojo con la trampa habitual: que todas las rutas funcionen no significa que el backend esté terminado. Significa que la Fase I está terminada. En la Fase II esas mismas rutas dejarán de ser abiertas y pasarán a exigir
JWT + RBAC.
Mapa mental del ISS
mindmap
root((CIERRE<br/>Fase I<br/>Business))
DoD
Cinco features
Cinco tablas
Cuatro capas por feature
DTO por operacion
SeedersRunner
Swagger
Estado
Sin autenticacion
Rutas abiertas
tsc sin errores
Verificacion
Matriz de pruebas
Smoke test de rutas
Norma de nombres
Cierre
Auditoria final
Pasa a Fase II
Pregunta que responde: ¿de qué trata este cierre y qué piezas lo componen?
Mapa del backend
Esta representación responde siempre a la misma pregunta: ¿en qué parte del backend estamos? Aquí es un mapa de balance de fase: la cadena completa de negocio está terminada; toda la seguridad es todavía objetivo.
IMPLEMENTADO HASTA ESTE CIERRE (Fase I — Business)
──────────────────────────────────────────────────
HTTP
↓
Routes → Controller → Service → Repository → Model → Sequelize → BD
✅ ✅ ✅ ✅ ✅ ✅
Features de negocio (cada una con sus 4 capas + dto/ + routes + seeder + swagger)
├── clients ✅
├── product-types ✅
├── products ✅ (+ products.associations.ts)
├── sales ✅ (+ sales.associations.ts)
└── product-sales ✅ (+ product-sales.associations.ts)
Infraestructura transversal
├── SeedersRunner + counts ✅
├── Swagger /api/docs ✅
└── Sin autenticación ✅ (todas las rutas SIN AUTH)
OBJETIVO DE ARQUITECTURA (Fase II — todavía no)
───────────────────────────────────────────────
├── Seguridad base (JWT HS256, bcrypt, AppError) 🎯 ISS-09
├── Feature users 🎯 ISS-10
├── Features roles y resources (58 recursos) 🎯 ISS-11
├── role_users y resource_roles (matriz RBAC) 🎯 ISS-12
├── middlewares authenticate / authorize 🎯 ISS-13
├── refresh_tokens (rotación, detección de reúso) 🎯 ISS-14
└── sesión (login / refresh / logout / perfil) 🎯 ISS-15
FUERA DE ALCANCE EN ESTE LAB
⬜ Nada queda fuera del curso: la seguridad es Fase II.
Pregunta que responde: ¿qué capas del backend existen ya al cerrar la Fase I y cuáles son todavía objetivo?
Mira el contraste: la columna de negocio está entera en verde y la de seguridad entera en 🎯. Eso es exactamente el estado del backend al terminar ISS-08.
Árbol de archivos
En un cierre no hay archivos nuevos: el documento no crea ni parchea nada. Por eso aquí se muestra el árbol consolidado de la fase, con la leyenda de lo que se construyó a lo largo de ISS-03 a ISS-08.
Leyenda: ★ = creado durante la Fase I · △ = existente parcheado durante la Fase I · ✅ = pieza verificada en este cierre.
Estructura antes
Archivos creados / modificados en este ISS
Estructura después
app-storelab-express/
├── src/
│ ├── config/index.ts ✅ △ arranque: modelos → asociaciones → rutas → Swagger
│ ├── database/
│ │ ├── db.ts ✅ conexión, testConnection, sync
│ │ └── seeders/{counts,index}.ts ✅ ★ SeedersRunner + conteos
│ ├── features/
│ │ └── business/ ✅
│ │ ├── clients/ ✅ ★ model + dto/ + repository + service + controller
│ │ │ ├── client.model.ts ✅ ★ Model (singular)
│ │ │ ├── dto/ ✅ ★ create / update / patch / response / index
│ │ │ ├── clients.repository.ts ✅ ★
│ │ │ ├── clients.service.ts ✅ ★
│ │ │ ├── clients.controller.ts ✅ ★
│ │ │ ├── clients.routes.ts ✅ ★ HTTP (SIN AUTH)
│ │ │ └── http/ clients.seeder.ts clients.swagger.ts ✅ ★
│ │ ├── product-types/ ✅ ★ mismas 4 capas + http + seeder + swagger
│ │ ├── products/ ✅ ★ + products.associations.ts
│ │ ├── sales/ ✅ ★ + sales.associations.ts
│ │ └── product-sales/ ✅ ★ pivote product_sales + associations
│ ├── routes/index.ts ✅ △ agregador de features
│ ├── shared/
│ │ ├── database/with-transaction.ts ✅ transacciones (unit of work)
│ │ ├── errors/app-error.ts ✅ errores de dominio
│ │ └── http/base-controller.ts ✅ controlador base
│ ├── swagger/index.ts ✅ △ registry OpenAPI
│ └── server.ts ✅ punto de entrada
└── …
El árbol no cambia con este cierre: su único efecto es que tú confirmas, carpeta por carpeta, que todo lo que debía existir existe.
Pregunta que responde: ¿el cierre modifica la estructura del proyecto y qué piezas de la fase puedo auditar en el árbol? — No la modifica; solo la consolida.
Flujos
Así viaja cualquier petición de la Fase I. Fíjate en que ninguna capa se salta a la siguiente:
sequenceDiagram
participant C as Cliente HTTP
participant R as Routes
participant Ct as Controller
participant S as Service
participant Rp as Repository
participant M as Model
participant DB as Sequelize y BD
C->>R: peticion REST
R->>Ct: ruta hacia controlador
Ct->>S: datos validados por el DTO
S->>Rp: operacion de negocio
Rp->>M: consulta al modelo
M->>DB: SQL
DB-->>M: filas
M-->>Rp: instancias
Rp-->>S: entidades
S-->>Ct: respuesta de dominio
Ct-->>C: JSON y codigo HTTP
Pregunta que responde: ¿por qué el DTO cruza routes/controller/service pero nunca llega al repository ni al model?
El DTO es el contrato de la API: describe lo que entra y sale por HTTP. El repository y el model no lo conocen; trabajan con entidades de Sequelize. Esa separación es la que hace que la Fase II pueda añadir middlewares antes del controller sin tocar la lógica de negocio.
Comandos explicados
El cierre no trae comandos nuevos: reutiliza los de la fase. Estos son los que demuestran que la Fase I está cerrada.
npx tsc --noEmit
COMANDO
↓
npx tsc --noEmit
↓
QUÉ HACE
Compila todo el proyecto con TypeScript y comprueba los tipos sin
generar archivos de salida.
↓
POR QUÉ SE NECESITA
Es el criterio de aceptación transversal del laboratorio: el árbol de
features completo (5 features, DTOs, asociaciones) debe tipar sin un
solo error.
↓
QUÉ CREA O MODIFICA
Nada. Es una verificación de solo lectura.
↓
RESULTADO ESPERADO
Sin salida y con código de salida 0.
↓
CÓMO VERIFICARLO
Si aparece cualquier error TS, el cierre falla: hay que corregir el
tipo antes de dar la fase por terminada.
npm run db:seed
COMANDO
↓
npm run db:seed
↓
QUÉ HACE
Ejecuta el SeedersRunner sobre todas las tablas de la fase.
↓
POR QUÉ SE NECESITA
Sin datos no se puede recorrer la matriz de pruebas: las rutas GET
necesitan filas reales que devolver.
↓
QUÉ CREA O MODIFICA
Puebla las 5 tablas de negocio (clients, product_types, products,
sales, product_sales) y sincroniza el esquema.
↓
RESULTADO ESPERADO
El runner arranca, imprime los conteos, siembra y termina con
«SeedersRunner finalizado».
↓
CÓMO VERIFICARLO
Una consulta GET a `/api/clientes` devuelve el arreglo de clientes
sembrados.
DB_SYNC_FORCE=true npm run dev
COMANDO
↓
DB_SYNC_FORCE=true npm run dev
↓
QUÉ HACE
Arranca el servidor forzando que `sync` recree las tablas.
↓
POR QUÉ SE NECESITA
Es la forma documentada de partir de una base limpia: recrea el
esquema y deja las FK snake_case listas para sembrar.
↓
QUÉ CREA O MODIFICA
Elimina y recrea las tablas desde los modelos y sus asociaciones.
↓
RESULTADO ESPERADO
«Base de datos recreada (DB_SYNC_FORCE=true)» y el servidor
escuchando en el puerto configurado.
↓
CÓMO VERIFICARLO
Tras recrear, ejecuta `npm run db:seed` y comprueba `/api/docs`.
La matriz de pruebas de la fase
Esta matriz se deriva del DoD del documento de cierre. Cada fila es un caso que debes ejecutar antes de dar el GATE por bueno. Las rutas salen del mapa de API del documento; los métodos, de su CRUD documentado.
| # | Caso | Método y ruta | Resultado esperado | Evidencia |
|---|---|---|---|---|
| 1 | Listar clientes | GET /api/clientes |
200 con el arreglo de clientes | Swagger / navegador |
| 2 | Crear cliente | POST /api/clientes |
201 con el cliente creado | Swagger |
| 3 | Actualizar cliente | PUT / PATCH /api/clientes/:id |
200 con el cliente actualizado | Swagger |
| 4 | Eliminar cliente | DELETE /api/clientes/:id |
200/204 sin el cliente | Swagger |
| 5 | Listar tipos de producto | GET /api/tipos-producto |
200 con el catálogo | Swagger |
| 6 | Crear tipo de producto | POST /api/tipos-producto |
201 con el tipo creado | Swagger |
| 7 | Listar productos | GET /api/productos |
200 con el catálogo | Swagger |
| 8 | Crear producto con tipo | POST /api/productos |
201 y FK product_type_id válida |
Swagger |
| 9 | Listar ventas | GET /api/ventas |
200 con cabeceras de venta | Swagger |
| 10 | Crear venta | POST /api/ventas |
201 con la cabecera | Swagger |
| 11 | Listar detalle de ventas | GET /api/detalle-ventas |
200 con las líneas (product_sales) |
Swagger |
| 12 | Crear detalle de venta | POST /api/detalle-ventas |
201 con la línea creada | Swagger |
| 13 | Documentación | GET /api/docs y GET /api/docs.json |
UI y JSON OpenAPI | Navegador |
| 14 | Sin autenticación | Cualquier ruta de negocio sin Authorization |
Responde con normalidad (SIN AUTH) | Swagger |
| 15 | Tipado global | npx tsc --noEmit |
Sin errores | Terminal |
Pregunta que responde: ¿qué casos mínimos demuestran que la Fase I está realmente cerrada?
Los casos 1–12 cubren la cadena completa por cada familia (cabecera y detalle en ventas); el 13–15 son los criterios transversales del DoD (Swagger, SIN AUTH y tipos).
Recorrido del ISS, paso a paso
Lo que sigue es la reproducción íntegra y verbatim del documento de cierre 10-cierre-business.md. Se inserta automáticamente al construir el cuaderno: los encabezados aparecen degradados un nivel para anidar bajo esta sección y los enlaces relativos se reescriben a ../manual/ para que abran correctamente desde docs/aprendizaje/. No se resume ni se reformatea nada.
Fase I: Business — Cierre del laboratorio (business SIN AUTH)
Contexto mínimo (autosuficiente). Si abres este archivo aislado —o lo llevas a otra IA—, esto es lo que hay que saber antes de ejecutarlo. - Proyecto:
app-storelab-express-ii— Express 5 + TypeScript + Sequelize, arquitectura por features, Fase I solo Business (sin auth ni roles). - Recorrido obligatorio de una petición:HTTP → Controller → Service → Repository → Model → Sequelize → BD. Ninguna capa se salta a la siguiente. - Diseño de datos (columnas, tipos, FKRESTRICT, índices, transacciones):../bd-storelab.md, Fase I — Business. - Capas, convenciones y reglas transversales:00-contexto.md.
Este ISS Título Cierre del laboratorio (business SIN AUTH) Feature / tabla las 5 tablas API todas Depende de ISS-08 — Feature Sale + ProductSale Habilita ISS-09 — Base de seguridad y modelos Auth Nota de Fase II. Este cierre describe el estado al terminar ISS-08 (business sin auth). Después, la Fase II (ISS-09 … ISS-15) protege todas estas rutas con
authenticate+authorizey añade identidades, RBAC y sesiones. La actualización de las rutas de negocio está en ISS-13 y el estado final del backend en el cierre de Fase II.
Contenido de este ISS
- DoD del laboratorio (business SIN AUTH)
- Norma de nombres (carpeta, clase, tabla, FK)
- Cómo repetir el patrón (otra entidad)
- Referencia rápida de paquetes
- Fuentes
DoD del laboratorio (business SIN AUTH)
Al cerrar ISS-08 el backend está completo para este lab:
- [ ] 5 features (carpeta en plural):
clients,product-types,products,sales,product-sales - [ ] Cada feature con sus 4 capas:
*.controller.ts→*.service.ts→*.repository.ts→*.model.ts - [ ] Cada feature con su DTO: carpeta
dto/(un archivo por operación +index.ts) - [ ] 5 tablas:
clients,product_types,products,sales,product_sales - [ ] APIs:
/api/clientes,/api/tipos-producto,/api/productos,/api/ventas,/api/detalle-ventas - [ ] SeedersRunner + Swagger
/api/docs - [ ] Sin autenticación ni autorización (todas las rutas SIN AUTH)
- [ ]
npx tsc --noEmitOK
Consulta de campos/tablas (opcional): |bd-storelab.md.
app-storelab-express/
├── src/
│ ├── config/index.ts
│ ├── database/
│ │ ├── db.ts
│ │ └── seeders/{counts,index}.ts
│ ├── features/
│ │ └── business/
│ │ ├── clients/
│ │ │ ├── client.model.ts # Model (singular)
│ │ │ ├── dto/ # DTOs (contrato de la API)
│ │ │ │ ├── create-client.dto.ts
│ │ │ │ ├── update-client.dto.ts
│ │ │ │ ├── patch-client.dto.ts
│ │ │ │ ├── client-response.dto.ts
│ │ │ │ └── index.ts
│ │ │ ├── clients.repository.ts # Repository
│ │ │ ├── clients.service.ts # Service
│ │ │ ├── clients.controller.ts # Controller
│ │ │ ├── clients.routes.ts # HTTP
│ │ │ └── http/ clients.seeder.ts clients.swagger.ts
│ │ ├── product-types/ # mismas 4 capas + http + seeder + swagger
│ │ ├── products/ # + products.associations.ts
│ │ ├── sales/ # cabecera + sales.associations.ts
│ │ └── product-sales/ # pivote product_sales + associations
│ ├── routes/index.ts
│ ├── shared/
│ │ ├── database/with-transaction.ts
│ │ ├── errors/app-error.ts
│ │ └── http/base-controller.ts
│ ├── swagger/index.ts
│ └── server.ts
└── …
| Método | Ruta | Nota |
|---|---|---|
| * | /api/clientes… |
SIN AUTH (ISS-03) |
| * | /api/tipos-producto… |
SIN AUTH (ISS-06) |
| * | /api/productos… |
SIN AUTH (ISS-07) |
| * | /api/ventas… |
SIN AUTH (ISS-08) |
| * | /api/detalle-ventas… |
SIN AUTH (ISS-08 · ProductSale) |
| GET | /api/docs |
Swagger UI |
| GET | /api/docs.json |
OpenAPI JSON |
Norma de nombres (carpeta, clase, tabla, FK)
| Pieza | Norma | Ejemplo |
|---|---|---|
| Carpeta feature | kebab-case plural | product-types/, product-sales/ |
| Archivos de capa | plural + sufijo | products.repository.ts, products.service.ts, products.controller.ts |
| Modelo / interfaz | singular | product.model.ts → Product, ProductI |
| DTO | carpeta dto/ + un archivo por operación |
dto/create-product.dto.ts → CreateProductDto |
| Clase | PascalCase singular | Client, ProductType, Sale, ProductSale |
| Tabla BD | snake_case plural (compuestos con _) |
clients, product_types, product_sales |
| FK | singular de la tabla referenciada + _id |
client_id, product_type_id, sale_id, product_id |
| Columnas de negocio | snake_case | min_stock, sale_date, unit_price, line_total |
| SeedCounts / JSON compuestos | snake_case | product_types, product_sales, product_type |
No uses camelCase en tablas (productTypes ❌ → product_types ✅).
En *.associations.ts:
Sale.belongsTo(Client, { foreignKey: "client_id", as: "client" });
Client.hasMany(Sale, { foreignKey: "client_id", as: "sales" });
ProductSale.belongsTo(Sale, { foreignKey: "sale_id", as: "sale" });
Sale.hasMany(ProductSale, { foreignKey: "sale_id", as: "items" });
Product.hasMany(ProductSale, { foreignKey: "product_id", as: "sale_items" });
Con BD limpia, sequelize.sync crea FKs snake_case desde modelos/*.associations.ts.
Opcional: DB_SYNC_FORCE=true npm run dev recrea tablas.
Cómo repetir el patrón (otra entidad)
ISS-n-A modelo + DTO + esqueletos repository/service/controller/routes + cableado
ISS-n-B…E CRUD en orden: getAll, getOne, create, update PUT/PATCH, delete físico/lógico
(cada paso toca las 3 capas: repository -> service -> controller) + http
ISS-n-F seeder + PARCHE counts/runner
ISS-n-G swagger + PARCHE registry
ISS-n-R si hay FK `tabla_singular_id`: associations.ts + PARCHE config
Regla de oro del lab:
routes -> controller -> service -> repository -> model. Ninguna capa se salta a la siguiente ni consulta el modelo directamente. El DTO es el contrato que cruzaroutes/controller/service; elrepositoryy elmodelno lo conocen.
Referencia rápida de paquetes
npm install express@^5.2.1 cors@^2.8.6 dotenv@^17.4.2 morgan@^1.12.1 \
sequelize@^6.37.8 mysql2@^3.24.4 pg@^8.23.0 pg-hstore@^2.3.4 \
tedious@^20.0.0 oracledb@^7.0.1 bcryptjs@^3.0.3 \
swagger-ui-express@^5.0.1
npm install -D typescript@~5.9.2 ts-node@^10.9.2 nodemon@^3.1.14 \
@types/node@^22.20.3 @types/express@^5.0.6 \
@types/cors@^2.8.19 @types/morgan@^1.9.10 \
@types/sequelize@^6.12.0 @types/bcryptjs@^3.0.0 \
@types/swagger-ui-express@^4.1.8 \
@faker-js/faker@^10.6.0
Fuentes
- Este manual es la única guía de construcción (ISS,
cat >>, PARCHE). bd-storelab.md— solo consulta: entidades business y sus campos (no es un paso de construcción).
Diagnóstico
| Síntoma | Causa probable | Solución |
|---|---|---|
Un model/tabla aparece en camelCase (productTypes) |
Se ignoró la norma de nombres | Renombrar a snake_case plural (product_types) desde el modelo y volver a sincronizar |
| Error de FK al sincronizar o sembrar | Orden de seeders incorrecto (hijos antes que padres) o base sucia | Sembrar en orden clients → product_types → products → sales → product_sales; si hace falta, recrear con DB_SYNC_FORCE=true npm run dev |
npx tsc --noEmit falla en DTOs |
DTO desalineado con el modelo o el index.ts del dto/ |
Corregir el tipo; el DTO es el contrato de la API y debe tipar |
| Una ruta responde pero las asociaciones no | Falta importar *.associations.ts en el arranque |
Revisar el cableado de config/index.ts (modelos → asociaciones) |
/api/docs no lista una familia |
Falta registrar su módulo en el registry de Swagger | Parchear swagger/index.ts con el *.swagger.ts de la feature |
Pregunta que responde: si el cierre no queda en verde, ¿por dónde empiezo a mirar?
Conexión con el resto del curso
flowchart LR
A["ISS-08<br/>sale y product-sale"] --> B["CIERRE-BUSINESS<br/>verificacion Fase I"]
B --> C["ISS-09<br/>base de seguridad"]
C --> D["ISS-10 ... ISS-15<br/>Auth con RBAC"]
D --> E["CIERRE-AUTH<br/>verificacion Fase II"]
Pregunta que responde: ¿qué ISS habilita este cierre y a qué documento da paso?
- Lo habilita: ISS-08, que cierra la última feature de negocio.
- Lo que habilita: ISS-09, la base de seguridad que protegerá todas estas rutas.
- Piezas reutilizadas: este cierre reutiliza el recorrido
routes → controller → service → repository → model, elSeedersRunner, el registry de Swagger y la norma de nombres. La Fase II no reescribe nada de esto: solo añade capas por delante. - Cierre hermano: el estado final del backend se verifica en el cuaderno de cierre de Fase II.
Glosario
| Término | Significado en este cierre |
|---|---|
| DoD | Definition of Done: el checklist que define qué significa «terminado» para la fase |
| Feature | Carpeta en plural bajo features/business/ que agrupa las 4 capas de una entidad |
| Capa | Cada uno de los eslabones controller → service → repository → model; ninguna se salta a la siguiente |
| DTO | Contrato de la API en dto/ (un archivo por operación + index.ts); cruza routes/controller/service |
| Asociación | Relación Sequelize declarada en *.associations.ts y llamada desde el arranque |
| Swagger / OpenAPI | Documentación viva de la API en /api/docs y /api/docs.json |
| Seeder / SeedersRunner | Poblador determinista de tablas; el runner orquesta el orden padre → hijo |
npx tsc --noEmit |
Compilación de tipos sin emitir archivos: criterio transversal del laboratorio |
Pregunta que responde: ¿qué vocabulario debo dominar para leer el DoD sin ambigüedad?
Criterios de aceptación
Los del documento fuente, textuales:
- [ ] 5 features (carpeta en plural):
clients,product-types,products,sales,product-sales - [ ] Cada feature con sus 4 capas:
*.controller.ts→*.service.ts→*.repository.ts→*.model.ts - [ ] Cada feature con su DTO: carpeta
dto/(un archivo por operación +index.ts) - [ ] 5 tablas:
clients,product_types,products,sales,product_sales - [ ] APIs:
/api/clientes,/api/tipos-producto,/api/productos,/api/ventas,/api/detalle-ventas - [ ] SeedersRunner + Swagger
/api/docs - [ ] Sin autenticación ni autorización (todas las rutas SIN AUTH)
- [ ]
npx tsc --noEmitOK
Evaluación
Preguntas de comprensión
-
¿Por qué el cierre de la Fase I no crea archivos? Porque no es un ISS de construcción sino de verificación: define el DoD y audita lo construido entre ISS-03 e ISS-08. Crear archivos aquí duplicaría responsabilidades y rompería la separación «construir vs. cerrar».
-
El backend funciona con todas sus rutas, ¿puedo afirmar que está terminado? No. Está terminada la Fase I (negocio). La seguridad —identidad, RBAC y sesiones— es la Fase II y llega en ISS-09…ISS-15. Confundir «funciona» con «terminado» es el error conceptual que este cierre previene.
-
¿Por qué el orden de las capas es
controller → service → repository → modely no puede alterarse? Porque cada capa solo conoce a la siguiente: el controller no consulta la BD, el service no habla HTTP, el repository no valida contratos y el model no contiene reglas de negocio. Saltarse una capa mezcla responsabilidades y hace imposible añadir middlewares o reutilizar lógica en la Fase II. -
¿Dónde vive el contrato de la API y hasta dónde llega? En la carpeta
dto/de cada feature (un archivo por operación +index.ts). El DTO cruzaroutes/controller/service; ni elrepositoryni elmodello conocen. -
¿Qué demuestra exactamente
npx tsc --noEmiten este cierre? Que el árbol completo de features (modelos, DTOs, asociaciones y cableado) tipa sin errores. Es un criterio transversal que ninguna feature puede incumplir. -
¿Por qué una petición sin
Authorizationdebe responder en la Fase I? Porque el DoD exige explícitamente «sin autenticación ni autorización». Si una ruta pidiera token, la fase estaría mal cerrada. Lo contrario (exigir token) solo será correcto a partir de ISS-13.
Ejercicios
Ejercicio 1 — Auditar la norma de nombres. Recorre las 5 features y anota, para una de ellas, el nombre de la carpeta, del modelo, de la tabla, de la FK y de la columna de negocio. Explica qué regla cumple cada uno.
Respuesta razonada
Para `product-sales`, por ejemplo: carpeta en kebab-case **plural** (`product-sales`), modelo en **singular** (`product-sale.model.ts` → `ProductSale`), tabla en snake_case plural (`product_sales`), FK con el singular de la tabla referenciada + `_id` (`sale_id`, `product_id`) y columnas de negocio en snake_case (`unit_price`, `line_total`). La regla evita la mezcla de convenciones: una sola norma por pieza, sin camelCase en tablas.Ejercicio 2 — Reproducir el orden de seeders. Escribe el orden en que el SeedersRunner debe poblar las tablas de negocio y justifica por qué ese orden y no otro.
Respuesta razonada
El orden es `clients → product_types → products → sales → product_sales`. Se siembra de **padres a hijos**: `sales` necesita que exista `clients` (FK `client_id`), y `product_sales` necesita que existan `sales` y `products` (FK `sale_id` y `product_id`). Sembrar un hijo antes que su padre provoca errores de FK.Ejercicio 3 — Diseñar un caso de prueba que falle si la fase está mal cerrada. Propón un caso que detecte que alguien dejó una ruta protegida por error durante la Fase I.
Respuesta razonada
Un caso que haga una petición a una ruta de negocio (por ejemplo `GET /api/clientes`) **sin** cabecera `Authorization` y espere una respuesta normal. Si el servidor responde `401` o `403`, alguien introdujo seguridad antes de tiempo: la Fase I exige «todas las rutas SIN AUTH». Este caso cubre exactamente el criterio del DoD que más fácil se rompe al copiar código de la Fase II.GATE
Para cerrar la Fase I, ejecuta en orden:
Resultado esperado:
npx tsc --noEmittermina sin errores.npm run db:seedsiembra las 5 tablas y termina con «SeedersRunner finalizado».- El servidor arranca y
/api/docsmuestra las 5 familias;/api/docs.jsonresponde.
Completa la verificación recorriendo la matriz de pruebas por Swagger.
Checklist de cierre:
- [ ] 5 features (
clients,product-types,products,sales,product-sales) con sus 4 capas - [ ] DTO por feature (
dto/con un archivo por operación +index.ts) - [ ] 5 tablas y sus 5 familias de API responden
- [ ] SeedersRunner y Swagger
/api/docsoperativos - [ ] Todas las rutas SIN AUTH (una petición sin token responde con normalidad)
- [ ]
npx tsc --noEmitOK
Con el checklist en verde, la Fase I está cerrada y puedes pasar al ISS-09 — Base de seguridad y modelos Auth, donde empieza la Fase II.
Navegación de la ruta: ← ISS-08 · 🛠 Construir · ↑ Ruta Express · → CIERRE-BUSINESS · 🛠 Construir