Saltar a contenido

📚 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/clientes sin 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 --noEmit termina 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

  1. Ficha del ISS
  2. Mapa mental del ISS
  3. Mapa del backend
  4. Árbol de archivos
  5. Flujos
  6. Comandos explicados
  7. La matriz de pruebas de la fase
  8. Recorrido del ISS, paso a paso
  9. Diagnóstico
  10. Conexión con el resto del curso
  11. Glosario
  12. Criterios de aceptación
  13. Evaluación
  14. 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

(estado al terminar ISS-08: idéntico a la estructura después)

Archivos creados / modificados en este ISS

(ninguno)

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, FK RESTRICT, í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 + authorize y 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 --noEmit OK

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 cruza routes/controller/service; el repository y el model no 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, el SeedersRunner, 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 --noEmit OK

Evaluación

Preguntas de comprensión

  1. ¿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».

  2. 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.

  3. ¿Por qué el orden de las capas es controller → service → repository → model y 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.

  4. ¿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 cruza routes/controller/service; ni el repository ni el model lo conocen.

  5. ¿Qué demuestra exactamente npx tsc --noEmit en 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.

  6. ¿Por qué una petición sin Authorization debe 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:

npx tsc --noEmit
npm run db:seed
npm run dev

Resultado esperado:

  • npx tsc --noEmit termina sin errores.
  • npm run db:seed siembra las 5 tablas y termina con «SeedersRunner finalizado».
  • El servidor arranca y /api/docs muestra las 5 familias; /api/docs.json responde.

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/docs operativos
  • [ ] Todas las rutas SIN AUTH (una petición sin token responde con normalidad)
  • [ ] npx tsc --noEmit OK

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