871 lines
25 KiB
Markdown
871 lines
25 KiB
Markdown
|
|
# 📋 SPEC - Arquitectura y Plan de Ejecución
|
||
|
|
## EMERGES TES - Backend de Gestión de Contenido
|
||
|
|
|
||
|
|
**Fecha:** 2025-01-25
|
||
|
|
**Versión:** 1.0
|
||
|
|
**Estado:** En Planificación
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 OBJETIVO
|
||
|
|
|
||
|
|
Crear un backend completo para gestionar todo el contenido médico de EMERGES TES:
|
||
|
|
- ✅ Protocolos (procedures)
|
||
|
|
- ✅ Vademécum (drugs)
|
||
|
|
- ✅ Guías de Refuerzo (guides)
|
||
|
|
- ✅ Glosario de Términos (glossary) - **NUEVO**
|
||
|
|
- ✅ Medios Audiovisuales (media)
|
||
|
|
- ✅ Sistema de Validación Médica mejorado
|
||
|
|
- ✅ Refactorización de archivos grandes
|
||
|
|
- ✅ Eliminación de duplicidades
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🏗️ ARQUITECTURA
|
||
|
|
|
||
|
|
### Patrón Arquitectónico: **Clean Architecture + Repository Pattern**
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ PRESENTATION LAYER │
|
||
|
|
│ (Express Routes + Middleware + Validators) │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ APPLICATION LAYER │
|
||
|
|
│ (Services: ContentService, DrugService, etc.) │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ DOMAIN LAYER │
|
||
|
|
│ (Entities, Value Objects, Domain Logic) │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ INFRASTRUCTURE LAYER │
|
||
|
|
│ (Repositories, Database, File Storage) │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Principios de Diseño
|
||
|
|
|
||
|
|
1. **Separación de Responsabilidades**
|
||
|
|
- Routes: Solo routing y validación de entrada
|
||
|
|
- Services: Lógica de negocio
|
||
|
|
- Repositories: Acceso a datos
|
||
|
|
- Entities: Modelos de dominio inmutables
|
||
|
|
|
||
|
|
2. **Inmutabilidad**
|
||
|
|
- Todas las entidades son inmutables
|
||
|
|
- Usar `readonly` en TypeScript
|
||
|
|
- Crear nuevas instancias en lugar de mutar
|
||
|
|
|
||
|
|
3. **Validación con Zod**
|
||
|
|
- Todos los inputs validados con Zod
|
||
|
|
- Schemas compartidos entre frontend y backend
|
||
|
|
- Validación en runtime, no solo en compile-time
|
||
|
|
|
||
|
|
4. **Funciones Pequeñas**
|
||
|
|
- Máximo 20-30 líneas por función
|
||
|
|
- Una sola responsabilidad
|
||
|
|
- Fácil de testear
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 MODELO DE DATOS
|
||
|
|
|
||
|
|
### 1. Content Items (Ya existe, mejorar)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Domain Entity
|
||
|
|
interface ContentItem {
|
||
|
|
readonly id: string;
|
||
|
|
readonly type: 'protocol' | 'guide' | 'manual' | 'checklist';
|
||
|
|
readonly slug: string;
|
||
|
|
readonly level: 'operativo' | 'formativo' | 'referencia';
|
||
|
|
readonly title: string;
|
||
|
|
readonly shortTitle?: string;
|
||
|
|
readonly description?: string;
|
||
|
|
readonly content: ContentData; // JSON estructurado
|
||
|
|
readonly contentMarkdown?: string;
|
||
|
|
readonly category?: string;
|
||
|
|
readonly subcategory?: string;
|
||
|
|
readonly priority: 'critica' | 'alta' | 'media' | 'baja';
|
||
|
|
readonly ageGroup?: 'adulto' | 'pediatrico' | 'neonatal' | 'todos';
|
||
|
|
readonly status: 'draft' | 'in_review' | 'approved' | 'published' | 'archived';
|
||
|
|
readonly version: number;
|
||
|
|
readonly latestVersion: number;
|
||
|
|
readonly validatedBy?: string;
|
||
|
|
readonly validatedAt?: Date;
|
||
|
|
readonly createdAt: Date;
|
||
|
|
readonly updatedAt: Date;
|
||
|
|
readonly createdBy: string;
|
||
|
|
readonly updatedBy: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Drugs (Ya existe, mejorar)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface Drug {
|
||
|
|
readonly id: string;
|
||
|
|
readonly slug: string;
|
||
|
|
readonly genericName: string;
|
||
|
|
readonly tradeName?: string;
|
||
|
|
readonly category: DrugCategory;
|
||
|
|
readonly line: 'first' | 'second';
|
||
|
|
readonly frequency: 'high' | 'medium' | 'low';
|
||
|
|
readonly presentation: string;
|
||
|
|
readonly adultDose: string;
|
||
|
|
readonly pediatricDose?: string;
|
||
|
|
readonly routes: readonly AdministrationRoute[];
|
||
|
|
readonly dilution?: string;
|
||
|
|
readonly indications: readonly string[];
|
||
|
|
readonly contraindications: readonly string[];
|
||
|
|
readonly sideEffects?: string;
|
||
|
|
readonly antidote?: string;
|
||
|
|
readonly notes: readonly string[];
|
||
|
|
readonly criticalPoints: readonly string[];
|
||
|
|
readonly source?: string;
|
||
|
|
readonly status: ContentStatus;
|
||
|
|
readonly version: string;
|
||
|
|
readonly createdAt: Date;
|
||
|
|
readonly updatedAt: Date;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Glossary (NUEVO)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface GlossaryTerm {
|
||
|
|
readonly id: string;
|
||
|
|
readonly term: string;
|
||
|
|
readonly abbreviation?: string;
|
||
|
|
readonly category: 'pharmaceutical' | 'anatomical' | 'clinical' | 'procedural';
|
||
|
|
readonly definition: string;
|
||
|
|
readonly context?: string; // Contexto de uso
|
||
|
|
readonly examples?: readonly string[];
|
||
|
|
readonly relatedTerms?: readonly string[]; // IDs de términos relacionados
|
||
|
|
readonly source?: string;
|
||
|
|
readonly status: ContentStatus;
|
||
|
|
readonly createdAt: Date;
|
||
|
|
readonly updatedAt: Date;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Media Resources (Ya existe, mejorar)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface MediaResource {
|
||
|
|
readonly id: string;
|
||
|
|
readonly type: 'image' | 'video' | 'audio' | 'document';
|
||
|
|
readonly path: string;
|
||
|
|
readonly filename: string;
|
||
|
|
readonly fileUrl: string;
|
||
|
|
readonly thumbnailUrl?: string;
|
||
|
|
readonly title?: string;
|
||
|
|
readonly description?: string;
|
||
|
|
readonly altText?: string;
|
||
|
|
readonly caption?: string;
|
||
|
|
readonly tags: readonly string[];
|
||
|
|
readonly block?: string;
|
||
|
|
readonly chapter?: string;
|
||
|
|
readonly priority: ContentPriority;
|
||
|
|
readonly width?: number;
|
||
|
|
readonly height?: number;
|
||
|
|
readonly format?: string;
|
||
|
|
readonly fileSize: number;
|
||
|
|
readonly durationSeconds?: number;
|
||
|
|
readonly status: ContentStatus;
|
||
|
|
readonly createdAt: Date;
|
||
|
|
readonly updatedAt: Date;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔐 VALIDACIÓN CON ZOD
|
||
|
|
|
||
|
|
### Schemas Compartidos
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// backend/src/validators/schemas/content.ts
|
||
|
|
import { z } from 'zod';
|
||
|
|
|
||
|
|
export const contentStatusSchema = z.enum([
|
||
|
|
'draft',
|
||
|
|
'in_review',
|
||
|
|
'approved',
|
||
|
|
'published',
|
||
|
|
'archived'
|
||
|
|
]);
|
||
|
|
|
||
|
|
export const contentPrioritySchema = z.enum([
|
||
|
|
'critica',
|
||
|
|
'alta',
|
||
|
|
'media',
|
||
|
|
'baja'
|
||
|
|
]);
|
||
|
|
|
||
|
|
export const contentTypeSchema = z.enum([
|
||
|
|
'protocol',
|
||
|
|
'guide',
|
||
|
|
'manual',
|
||
|
|
'checklist'
|
||
|
|
]);
|
||
|
|
|
||
|
|
export const contentLevelSchema = z.enum([
|
||
|
|
'operativo',
|
||
|
|
'formativo',
|
||
|
|
'referencia'
|
||
|
|
]);
|
||
|
|
|
||
|
|
export const ageGroupSchema = z.enum([
|
||
|
|
'adulto',
|
||
|
|
'pediatrico',
|
||
|
|
'neonatal',
|
||
|
|
'todos'
|
||
|
|
]);
|
||
|
|
|
||
|
|
// Schema para crear contenido
|
||
|
|
export const createContentSchema = z.object({
|
||
|
|
type: contentTypeSchema,
|
||
|
|
slug: z.string().min(1).max(200).regex(/^[a-z0-9-]+$/),
|
||
|
|
level: contentLevelSchema,
|
||
|
|
title: z.string().min(1).max(500),
|
||
|
|
shortTitle: z.string().max(200).optional(),
|
||
|
|
description: z.string().max(2000).optional(),
|
||
|
|
content: z.record(z.unknown()), // JSON estructurado
|
||
|
|
contentMarkdown: z.string().optional(),
|
||
|
|
category: z.string().max(100).optional(),
|
||
|
|
subcategory: z.string().max(100).optional(),
|
||
|
|
priority: contentPrioritySchema,
|
||
|
|
ageGroup: ageGroupSchema.optional(),
|
||
|
|
tags: z.array(z.string()).optional(),
|
||
|
|
});
|
||
|
|
|
||
|
|
// Schema para actualizar contenido
|
||
|
|
export const updateContentSchema = createContentSchema.partial().extend({
|
||
|
|
id: z.string().min(1),
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📁 ESTRUCTURA DE CARPETAS PROPUESTA
|
||
|
|
|
||
|
|
```
|
||
|
|
backend/
|
||
|
|
├── src/
|
||
|
|
│ ├── domain/ # 🆕 DOMAIN LAYER
|
||
|
|
│ │ ├── entities/
|
||
|
|
│ │ │ ├── ContentItem.ts
|
||
|
|
│ │ │ ├── Drug.ts
|
||
|
|
│ │ │ ├── GlossaryTerm.ts
|
||
|
|
│ │ │ └── MediaResource.ts
|
||
|
|
│ │ ├── value-objects/
|
||
|
|
│ │ │ ├── ContentStatus.ts
|
||
|
|
│ │ │ ├── ContentPriority.ts
|
||
|
|
│ │ │ └── Version.ts
|
||
|
|
│ │ └── repositories/ # Interfaces de repositorios
|
||
|
|
│ │ ├── IContentRepository.ts
|
||
|
|
│ │ ├── IDrugRepository.ts
|
||
|
|
│ │ ├── IGlossaryRepository.ts
|
||
|
|
│ │ └── IMediaRepository.ts
|
||
|
|
│ │
|
||
|
|
│ ├── application/ # 🆕 APPLICATION LAYER
|
||
|
|
│ │ ├── services/
|
||
|
|
│ │ │ ├── ContentService.ts
|
||
|
|
│ │ │ ├── DrugService.ts
|
||
|
|
│ │ │ ├── GlossaryService.ts
|
||
|
|
│ │ │ ├── MediaService.ts
|
||
|
|
│ │ │ └── ValidationService.ts
|
||
|
|
│ │ └── use-cases/
|
||
|
|
│ │ ├── CreateContentUseCase.ts
|
||
|
|
│ │ ├── UpdateContentUseCase.ts
|
||
|
|
│ │ ├── SubmitForReviewUseCase.ts
|
||
|
|
│ │ └── ApproveContentUseCase.ts
|
||
|
|
│ │
|
||
|
|
│ ├── infrastructure/ # 🆕 INFRASTRUCTURE LAYER
|
||
|
|
│ │ ├── repositories/
|
||
|
|
│ │ │ ├── ContentRepository.ts
|
||
|
|
│ │ │ ├── DrugRepository.ts
|
||
|
|
│ │ │ ├── GlossaryRepository.ts
|
||
|
|
│ │ │ └── MediaRepository.ts
|
||
|
|
│ │ ├── storage/
|
||
|
|
│ │ │ ├── FileStorage.ts
|
||
|
|
│ │ │ └── MediaStorage.ts
|
||
|
|
│ │ └── database/
|
||
|
|
│ │ └── migrations/
|
||
|
|
│ │
|
||
|
|
│ ├── presentation/ # Routes + Middleware
|
||
|
|
│ │ ├── routes/
|
||
|
|
│ │ │ ├── content.ts
|
||
|
|
│ │ │ ├── drugs.ts
|
||
|
|
│ │ │ ├── glossary.ts # 🆕
|
||
|
|
│ │ │ ├── media.ts
|
||
|
|
│ │ │ └── validation.ts
|
||
|
|
│ │ ├── middleware/
|
||
|
|
│ │ │ ├── auth.ts
|
||
|
|
│ │ │ ├── validate.ts
|
||
|
|
│ │ │ └── rate-limit.ts
|
||
|
|
│ │ └── validators/
|
||
|
|
│ │ ├── content.ts
|
||
|
|
│ │ ├── drugs.ts
|
||
|
|
│ │ ├── glossary.ts # 🆕
|
||
|
|
│ │ └── media.ts
|
||
|
|
│ │
|
||
|
|
│ └── shared/ # Código compartido
|
||
|
|
│ ├── types/
|
||
|
|
│ ├── errors/
|
||
|
|
│ └── utils/
|
||
|
|
│
|
||
|
|
└── database/
|
||
|
|
└── migrations/
|
||
|
|
├── 004_create_glossary_schema.sql # 🆕
|
||
|
|
└── 005_improve_media_schema.sql # 🆕
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎫 PLAN DE EJECUCIÓN (TICKETS)
|
||
|
|
|
||
|
|
### FASE 1: FUNDACIÓN Y REFACTORIZACIÓN
|
||
|
|
|
||
|
|
#### Ticket 1.1: Crear estructura de carpetas Clean Architecture
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 2 horas
|
||
|
|
**Patrón:** Arquitectura en capas
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear carpetas `domain/`, `application/`, `infrastructure/`
|
||
|
|
- [ ] Mover código existente a capas apropiadas
|
||
|
|
- [ ] Crear interfaces de repositorios
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Estructura de carpetas creada
|
||
|
|
- ✅ Código existente reorganizado
|
||
|
|
- ✅ Interfaces de repositorios definidas
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 1.2: Crear schemas Zod compartidos
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 3 horas
|
||
|
|
**Patrón:** Schema-First Design
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear `backend/src/shared/schemas/` con todos los schemas Zod
|
||
|
|
- [ ] Schemas para ContentItem, Drug, GlossaryTerm, MediaResource
|
||
|
|
- [ ] Schemas para operaciones CRUD
|
||
|
|
- [ ] Exportar tipos TypeScript desde schemas
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Todos los schemas Zod creados
|
||
|
|
- ✅ Tipos TypeScript generados desde schemas
|
||
|
|
- ✅ Validación completa de todos los campos
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 1.3: Refactorizar archivos grandes (drugs.ts)
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 4 horas
|
||
|
|
**Patrón:** Split Large Files
|
||
|
|
|
||
|
|
**Problema:** `drugs.ts` tiene 1363 líneas
|
||
|
|
|
||
|
|
**Solución:**
|
||
|
|
```
|
||
|
|
src/data/drugs/
|
||
|
|
├── index.ts # Exporta todo
|
||
|
|
├── types.ts # Tipos e interfaces
|
||
|
|
├── schemas.ts # Schemas Zod
|
||
|
|
├── cardiovascular.ts # Fármacos cardiovasculares
|
||
|
|
├── respiratorio.ts # Fármacos respiratorios
|
||
|
|
├── neurologico.ts # Fármacos neurológicos
|
||
|
|
├── analgesia.ts # Analgesia
|
||
|
|
├── oxigenoterapia.ts # Oxigenoterapia
|
||
|
|
└── otros.ts # Otros fármacos
|
||
|
|
```
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Dividir `drugs.ts` por categoría
|
||
|
|
- [ ] Crear `types.ts` con interfaces
|
||
|
|
- [ ] Crear `schemas.ts` con Zod schemas
|
||
|
|
- [ ] Mantener `index.ts` para compatibilidad
|
||
|
|
- [ ] Actualizar imports en componentes
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Archivo dividido en módulos <200 líneas cada uno
|
||
|
|
- ✅ Sin duplicación de código
|
||
|
|
- ✅ Todos los tests pasan
|
||
|
|
- ✅ Imports actualizados
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 1.4: Refactorizar archivos grandes (procedures.ts)
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 4 horas
|
||
|
|
**Patrón:** Split Large Files
|
||
|
|
|
||
|
|
**Problema:** `procedures.ts` tiene 3584 líneas
|
||
|
|
|
||
|
|
**Solución:**
|
||
|
|
```
|
||
|
|
src/data/procedures/
|
||
|
|
├── index.ts # Exporta todo
|
||
|
|
├── types.ts # Tipos e interfaces
|
||
|
|
├── schemas.ts # Schemas Zod
|
||
|
|
├── soporte-vital.ts # Protocolos soporte vital
|
||
|
|
├── patologias.ts # Protocolos patologías
|
||
|
|
├── escena.ts # Protocolos escena
|
||
|
|
└── shared.ts # Utilidades compartidas
|
||
|
|
```
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Dividir `procedures.ts` por categoría
|
||
|
|
- [ ] Crear `types.ts` con interfaces
|
||
|
|
- [ ] Crear `schemas.ts` con Zod schemas
|
||
|
|
- [ ] Mantener `index.ts` para compatibilidad
|
||
|
|
- [ ] Actualizar imports en componentes
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Archivo dividido en módulos <300 líneas cada uno
|
||
|
|
- ✅ Sin duplicación de código
|
||
|
|
- ✅ Todos los tests pasan
|
||
|
|
- ✅ Imports actualizados
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 1.5: Eliminar duplicidades en código
|
||
|
|
**Prioridad:** Media
|
||
|
|
**Estimación:** 3 horas
|
||
|
|
**Patrón:** DRY (Don't Repeat Yourself)
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Buscar código duplicado con herramientas (jscpd, etc.)
|
||
|
|
- [ ] Extraer funciones comunes a `shared/utils/`
|
||
|
|
- [ ] Crear hooks compartidos si aplica
|
||
|
|
- [ ] Eliminar imports no usados
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Código duplicado <5%
|
||
|
|
- ✅ Funciones comunes extraídas
|
||
|
|
- ✅ Sin imports no usados
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### FASE 2: GLOSARIO (NUEVO)
|
||
|
|
|
||
|
|
#### Ticket 2.1: Crear schema de base de datos para glosario
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 2 horas
|
||
|
|
**Patrón:** Database-First
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear migración `004_create_glossary_schema.sql`
|
||
|
|
- [ ] Tabla `glossary_terms` con campos necesarios
|
||
|
|
- [ ] Índices para búsqueda full-text
|
||
|
|
- [ ] Relaciones con otros contenidos
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Migración creada y testeada
|
||
|
|
- ✅ Índices optimizados
|
||
|
|
- ✅ Constraints de integridad
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 2.2: Crear entidad GlossaryTerm en dominio
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 2 horas
|
||
|
|
**Patrón:** Domain-Driven Design
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear `domain/entities/GlossaryTerm.ts`
|
||
|
|
- [ ] Definir interfaz inmutable
|
||
|
|
- [ ] Crear value objects necesarios
|
||
|
|
- [ ] Validaciones de dominio
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Entidad inmutable creada
|
||
|
|
- ✅ Validaciones de dominio implementadas
|
||
|
|
- ✅ Value objects definidos
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 2.3: Crear repositorio de glosario
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 3 horas
|
||
|
|
**Patrón:** Repository Pattern
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear `infrastructure/repositories/GlossaryRepository.ts`
|
||
|
|
- [ ] Implementar `IGlossaryRepository`
|
||
|
|
- [ ] Métodos CRUD completos
|
||
|
|
- [ ] Búsqueda full-text
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Repositorio implementado
|
||
|
|
- ✅ Todos los métodos CRUD funcionan
|
||
|
|
- ✅ Búsqueda full-text optimizada
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 2.4: Crear servicio de glosario
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 3 horas
|
||
|
|
**Patrón:** Service Layer
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear `application/services/GlossaryService.ts`
|
||
|
|
- [ ] Lógica de negocio para glosario
|
||
|
|
- [ ] Validaciones con Zod
|
||
|
|
- [ ] Manejo de errores
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Servicio implementado
|
||
|
|
- ✅ Validaciones completas
|
||
|
|
- ✅ Manejo de errores robusto
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 2.5: Crear rutas API para glosario
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 2 horas
|
||
|
|
**Patrón:** RESTful API
|
||
|
|
|
||
|
|
**Endpoints:**
|
||
|
|
- `GET /api/glossary` - Listar términos
|
||
|
|
- `GET /api/glossary/:id` - Obtener término
|
||
|
|
- `POST /api/glossary` - Crear término
|
||
|
|
- `PUT /api/glossary/:id` - Actualizar término
|
||
|
|
- `DELETE /api/glossary/:id` - Eliminar término
|
||
|
|
- `GET /api/glossary/search?q=...` - Buscar términos
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Crear `routes/glossary.ts`
|
||
|
|
- [ ] Implementar todos los endpoints
|
||
|
|
- [ ] Validación con Zod middleware
|
||
|
|
- [ ] Autenticación y permisos
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Todos los endpoints implementados
|
||
|
|
- ✅ Validación completa
|
||
|
|
- ✅ Tests de integración pasan
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 2.6: Migrar glosarios existentes del frontend al backend
|
||
|
|
**Prioridad:** Media
|
||
|
|
**Estimación:** 3 horas
|
||
|
|
**Patrón:** Data Migration
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Leer `pharmaceutical-terminology.ts`
|
||
|
|
- [ ] Leer `anatomical-terminology.ts`
|
||
|
|
- [ ] Crear script de migración
|
||
|
|
- [ ] Insertar datos en base de datos
|
||
|
|
- [ ] Verificar integridad
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Todos los términos migrados
|
||
|
|
- ✅ Sin pérdida de datos
|
||
|
|
- ✅ Relaciones creadas correctamente
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### FASE 3: MEJORAS DE VALIDACIÓN MÉDICA
|
||
|
|
|
||
|
|
#### Ticket 3.1: Mejorar sistema de validación médica
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 4 horas
|
||
|
|
**Patrón:** State Machine
|
||
|
|
|
||
|
|
**Mejoras:**
|
||
|
|
- [ ] Workflow completo: draft → in_review → approved → published
|
||
|
|
- [ ] Notificaciones a revisores
|
||
|
|
- [ ] Historial de cambios detallado
|
||
|
|
- [ ] Comentarios de revisión
|
||
|
|
- [ ] Aprobación por múltiples revisores (opcional)
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Mejorar `ValidationService`
|
||
|
|
- [ ] Crear máquina de estados
|
||
|
|
- [ ] Sistema de notificaciones
|
||
|
|
- [ ] Historial mejorado
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Workflow completo implementado
|
||
|
|
- ✅ Notificaciones funcionan
|
||
|
|
- ✅ Historial completo
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 3.2: Crear dashboard de revisión médica
|
||
|
|
**Prioridad:** Media
|
||
|
|
**Estimación:** 5 horas
|
||
|
|
**Patrón:** Admin Dashboard
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Endpoint `GET /api/validation/dashboard`
|
||
|
|
- [ ] Estadísticas de contenido pendiente
|
||
|
|
- [ ] Filtros por tipo, prioridad, fecha
|
||
|
|
- [ ] Vista de historial de validación
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Dashboard funcional
|
||
|
|
- ✅ Estadísticas correctas
|
||
|
|
- ✅ Filtros funcionan
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### FASE 4: MEJORAS DE MEDIOS AUDIOVISUALES
|
||
|
|
|
||
|
|
#### Ticket 4.1: Mejorar sistema de upload de medios
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 4 horas
|
||
|
|
**Patrón:** File Upload Service
|
||
|
|
|
||
|
|
**Mejoras:**
|
||
|
|
- [ ] Upload múltiple de archivos
|
||
|
|
- [ ] Procesamiento automático (thumbnails, optimización)
|
||
|
|
- [ ] Validación de tipos y tamaños
|
||
|
|
- [ ] Asociación fácil con contenido
|
||
|
|
- [ ] Preview antes de guardar
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Mejorar `MediaService`
|
||
|
|
- [ ] Procesamiento de imágenes (sharp)
|
||
|
|
- [ ] Generación de thumbnails
|
||
|
|
- [ ] Validación mejorada
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Upload múltiple funciona
|
||
|
|
- ✅ Thumbnails generados automáticamente
|
||
|
|
- ✅ Validación completa
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 4.2: Crear interfaz de gestión de medios
|
||
|
|
**Prioridad:** Media
|
||
|
|
**Estimación:** 5 horas
|
||
|
|
**Patrón:** Media Library
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Endpoint `GET /api/media/library`
|
||
|
|
- [ ] Búsqueda y filtros
|
||
|
|
- [ ] Vista de galería
|
||
|
|
- [ ] Asociación con contenido
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Biblioteca de medios funcional
|
||
|
|
- ✅ Búsqueda rápida
|
||
|
|
- ✅ Asociación fácil
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### FASE 5: TESTING Y CALIDAD
|
||
|
|
|
||
|
|
#### Ticket 5.1: Crear tests unitarios para servicios
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 6 horas
|
||
|
|
**Patrón:** Unit Testing
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Tests para `ContentService`
|
||
|
|
- [ ] Tests para `DrugService`
|
||
|
|
- [ ] Tests para `GlossaryService`
|
||
|
|
- [ ] Tests para `MediaService`
|
||
|
|
- [ ] Cobertura >80%
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Tests unitarios creados
|
||
|
|
- ✅ Cobertura >80%
|
||
|
|
- ✅ Todos los tests pasan
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
#### Ticket 5.2: Crear tests de integración para API
|
||
|
|
**Prioridad:** Alta
|
||
|
|
**Estimación:** 4 horas
|
||
|
|
**Patrón:** Integration Testing
|
||
|
|
|
||
|
|
**Tareas:**
|
||
|
|
- [ ] Tests para rutas de contenido
|
||
|
|
- [ ] Tests para rutas de fármacos
|
||
|
|
- [ ] Tests para rutas de glosario
|
||
|
|
- [ ] Tests para rutas de medios
|
||
|
|
|
||
|
|
**Criterios de aceptación:**
|
||
|
|
- ✅ Tests de integración creados
|
||
|
|
- ✅ Todos los endpoints testeados
|
||
|
|
- ✅ Tests pasan en CI/CD
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 REGLAS DE CALIDAD Y SEGURIDAD
|
||
|
|
|
||
|
|
### Higiene de Código
|
||
|
|
- ✅ Funciones máximo 20-30 líneas
|
||
|
|
- ✅ Una sola responsabilidad por función
|
||
|
|
- ✅ Nombres descriptivos
|
||
|
|
- ✅ Sin código comentado
|
||
|
|
- ✅ Sin imports no usados
|
||
|
|
|
||
|
|
### Validación
|
||
|
|
- ✅ Todos los inputs validados con Zod
|
||
|
|
- ✅ Validación en runtime
|
||
|
|
- ✅ Mensajes de error claros
|
||
|
|
- ✅ Validación de tipos médicos críticos
|
||
|
|
|
||
|
|
### Testing
|
||
|
|
- ✅ Tests unitarios para servicios
|
||
|
|
- ✅ Tests de integración para API
|
||
|
|
- ✅ Cobertura mínima 80%
|
||
|
|
- ✅ Tests antes o simultáneos a implementación
|
||
|
|
|
||
|
|
### Privacidad y Seguridad
|
||
|
|
- ✅ No exponer datos sensibles
|
||
|
|
- ✅ Validación de permisos en todas las rutas
|
||
|
|
- ✅ Rate limiting en endpoints críticos
|
||
|
|
- ✅ Logs de auditoría completos
|
||
|
|
- ✅ Sanitización de inputs
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 NOTAS IMPORTANTES
|
||
|
|
|
||
|
|
1. **Compatibilidad hacia atrás:** Mantener compatibilidad con frontend existente durante la migración
|
||
|
|
2. **Migración gradual:** Migrar contenido gradualmente, no todo de una vez
|
||
|
|
3. **Validación médica:** Todo contenido médico debe pasar por validación antes de publicarse
|
||
|
|
4. **Offline-first:** El frontend debe seguir funcionando offline con datos cacheados
|
||
|
|
5. **Performance:** Optimizar queries de base de datos, usar índices apropiados
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 RESPUESTAS A ENTREVISTA TÉCNICA
|
||
|
|
|
||
|
|
### 2. Validación de Dosis
|
||
|
|
|
||
|
|
**Rangos máximos/mínimos por edad/peso:** ✅ SÍ
|
||
|
|
- Ver documento: `docs/SISTEMA_VALIDACION_DOSIS.md`
|
||
|
|
- Sistema completo de validación con rangos por grupo de edad
|
||
|
|
- Validación de peso para edad
|
||
|
|
- Cálculo automático de dosis pediátricas
|
||
|
|
|
||
|
|
**Validación de cálculos pediátricos:** ✅ SÍ
|
||
|
|
- Cálculo por peso (mg/kg)
|
||
|
|
- Cálculo por superficie corporal (mg/m²)
|
||
|
|
- Validación de rangos seguros
|
||
|
|
- Alertas para dosis en límites
|
||
|
|
|
||
|
|
### 3. Validación de Protocolos
|
||
|
|
|
||
|
|
**Validación de secuencia de pasos:** ✅ SÍ
|
||
|
|
- Ver documento: `docs/SISTEMA_VALIDACION_PROTOCOLOS.md`
|
||
|
|
- Validación de orden secuencial
|
||
|
|
- Detección de pasos faltantes
|
||
|
|
- Validación de pasos críticos obligatorios
|
||
|
|
|
||
|
|
**Dependencias entre protocolos:** ✅ SÍ
|
||
|
|
- Prerequisitos (debe ejecutarse antes)
|
||
|
|
- Protocolos siguientes (normalmente lleva a)
|
||
|
|
- Alternativos (mutuamente excluyentes)
|
||
|
|
- Complementarios (se usan juntos)
|
||
|
|
|
||
|
|
### 4. Contenido Médico
|
||
|
|
|
||
|
|
**Quién valida:** ✅ Definido
|
||
|
|
- Ver documento: `docs/SISTEMA_VALIDACION_MEDICA.md`
|
||
|
|
- **Editor:** Crea y envía a revisión
|
||
|
|
- **Revisor Médico:** Revisa y aprueba/rechaza
|
||
|
|
- **Validador Médico:** Validación final contra guías oficiales
|
||
|
|
- **Publicador:** Publica contenido aprobado
|
||
|
|
|
||
|
|
**Flujo de aprobación:** ✅ Definido
|
||
|
|
```
|
||
|
|
DRAFT → IN_REVIEW → APPROVED → PUBLISHED
|
||
|
|
↓ ↓
|
||
|
|
└─────────┘ (REJECTED vuelve a DRAFT)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. Errores Críticos
|
||
|
|
|
||
|
|
**Qué errores bloquean acciones:** ✅ Definido
|
||
|
|
- Ver documento: `docs/ERRORES_CRITICOS_MEDICOS.md`
|
||
|
|
- Dosis fuera de rango seguro → BLOQUEA
|
||
|
|
- Dosis letal → BLOQUEA
|
||
|
|
- Paso crítico omitido → BLOQUEA
|
||
|
|
- Prerequisito no cumplido → BLOQUEA
|
||
|
|
- Contenido no validado → BLOQUEA publicación
|
||
|
|
- Peso inválido para edad → BLOQUEA
|
||
|
|
|
||
|
|
### 6. Separación de Capas
|
||
|
|
|
||
|
|
**Arquitectura:** ✅ Clean Architecture
|
||
|
|
- Ver documento: `docs/SEPARACION_CAPAS_LOGICA_NEGOCIO.md`
|
||
|
|
- **Domain:** Entidades, Value Objects, Lógica pura
|
||
|
|
- **Application:** Casos de uso, Servicios
|
||
|
|
- **Infrastructure:** Repositorios, BD, Storage
|
||
|
|
- **Presentation:** Routes, Middleware, Validators
|
||
|
|
|
||
|
|
**Lógica de negocio:** ✅ Organizada
|
||
|
|
- Domain Services para lógica de dominio pura
|
||
|
|
- Application Services para orquestación
|
||
|
|
- Use Cases para casos de uso específicos
|
||
|
|
|
||
|
|
### 7. Casos de Borde
|
||
|
|
|
||
|
|
**Análisis completo:** ✅ Documentado
|
||
|
|
- Ver documento: `docs/CASOS_BORDE.md`
|
||
|
|
- Casos de borde analizados uno por uno
|
||
|
|
- Soluciones propuestas para cada caso
|
||
|
|
- Validaciones definidas
|
||
|
|
|
||
|
|
### 8. Logs y Datos de Relevancia
|
||
|
|
|
||
|
|
**Sistema de logs:** ✅ Definido
|
||
|
|
- Ver documento: `docs/LOGS_AUDITORIA.md`
|
||
|
|
- **NO datos sensibles:** No se registran nombres, DNI, etc.
|
||
|
|
- **SÍ acciones del sistema:** Audit logs completos
|
||
|
|
- **SÍ validaciones:** Validation logs
|
||
|
|
- **SÍ errores críticos:** Error logs con notificaciones
|
||
|
|
- **SÍ estadísticas agregadas:** Sin identificar pacientes
|
||
|
|
|
||
|
|
### 9. Testing
|
||
|
|
|
||
|
|
**Cobertura mínima:** ✅ 80%
|
||
|
|
- Ver documento: `docs/TESTING_MOCKS_DATOS_MEDICOS.md`
|
||
|
|
- Domain Layer: 90%+
|
||
|
|
- Application Layer: 85%+
|
||
|
|
- Infrastructure Layer: 70%+
|
||
|
|
- Presentation Layer: 75%+
|
||
|
|
|
||
|
|
**Mocks para datos médicos:** ✅ Explicado
|
||
|
|
- Mocks de repositorios
|
||
|
|
- Fixtures de datos médicos de prueba
|
||
|
|
- Mocks de servicios externos
|
||
|
|
- Ejemplos completos incluidos
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🚀 PRÓXIMOS PASOS
|
||
|
|
|
||
|
|
1. ✅ Revisar y aprobar este SPEC
|
||
|
|
2. ✅ Crear `.cursorrules` con reglas de calidad
|
||
|
|
3. ✅ Documentos técnicos creados:
|
||
|
|
- `docs/SISTEMA_VALIDACION_DOSIS.md`
|
||
|
|
- `docs/SISTEMA_VALIDACION_PROTOCOLOS.md`
|
||
|
|
- `docs/SISTEMA_VALIDACION_MEDICA.md`
|
||
|
|
- `docs/ERRORES_CRITICOS_MEDICOS.md`
|
||
|
|
- `docs/SEPARACION_CAPAS_LOGICA_NEGOCIO.md`
|
||
|
|
- `docs/CASOS_BORDE.md`
|
||
|
|
- `docs/LOGS_AUDITORIA.md`
|
||
|
|
- `docs/TESTING_MOCKS_DATOS_MEDICOS.md`
|
||
|
|
4. Comenzar con Fase 1 (Fundación y Refactorización)
|
||
|
|
5. Implementar tickets en orden de prioridad
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Fin del SPEC**
|