# Sistema de Registro de Estudiantes Sistema web para gestionar inscripciones de estudiantes en materias con restricciones de créditos y profesores. ## Stack Tecnológico | Capa | Tecnología | |------|------------| | Backend | .NET 10, C# | | API | GraphQL (HotChocolate) | | Frontend | Angular 21, TypeScript | | Base de Datos | SQL Server 2022 | | ORM | Entity Framework Core | | UI | Angular Material | ## Reglas de Negocio - 10 materias, cada una vale 3 créditos - 5 profesores, cada uno imparte 2 materias - Estudiantes pueden inscribir **máximo 3 materias** (9 créditos) - **Restricción:** Un estudiante NO puede tener materias con el mismo profesor ## Características del Sistema ### Funcionalidades - CRUD completo de estudiantes - Inscripción/cancelación de materias con validación de reglas - Visualización de compañeros de clase por materia - Interfaz responsive con Angular Material - **Sistema de autenticación con flujo de activación** - **Control de acceso por roles (Admin/Student)** ### Calidad y Robustez - **Manejo de errores**: Mensajes amigables para usuarios + logging detallado para desarrolladores - **Monitoreo de conectividad**: Verificación cada 5 segundos con overlay bloqueante si se pierde conexión - **Validación**: FluentValidation en backend + validación reactiva en frontend - **Arquitectura**: Clean Architecture + CQRS + Ports & Adapters ### DevOps - **Docker Compose**: Despliegue optimizado con un solo comando (`./start.sh`) - **Health Check**: Endpoint `/health` con verificación de base de datos - **Diagramas UML**: 8 diagramas PlantUML documentando la arquitectura ## Requisitos Previos - [.NET 10 SDK](https://dotnet.microsoft.com/download) - [Node.js 22+](https://nodejs.org/) - [Docker](https://www.docker.com/) (para SQL Server) - Angular CLI 21: `npm install -g @angular/cli` ## Inicio Rápido ### Paso 1: Clonar e ir al directorio ```bash git clone cd Interrapidisimo ``` ### Paso 2: Iniciar SQL Server con Docker ```bash docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Asde71.4Asde71.4" \ -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest ``` Esperar ~10 segundos a que inicie completamente. ### Paso 3: Configurar y ejecutar Backend ```bash cd src/backend # 1. Instalar herramienta EF Core (solo primera vez) dotnet tool install --global dotnet-ef # Si ya está instalada, ignorar el mensaje # 2. Restaurar dependencias dotnet restore # 3. Crear base de datos y aplicar migraciones dotnet ef database update -p Adapters/Driven/Persistence -s Host # NOTA: El mensaje "HostAbortedException" es NORMAL - indica que las migraciones se completaron # 4. Liberar puerto si está ocupado (opcional) fuser -k 5000/tcp 2>/dev/null # 5. Ejecutar API dotnet run --project Host ``` **API GraphQL:** http://localhost:5000/graphql ### Paso 4: Verificar que funciona En otra terminal: ```bash # Consultar materias (debe retornar 10) curl -s http://localhost:5000/graphql -X POST \ -H "Content-Type: application/json" \ -d '{"query":"{ subjects { id name credits } }"}' | jq . # Crear un estudiante curl -s http://localhost:5000/graphql -X POST \ -H "Content-Type: application/json" \ -d '{"query":"mutation { createStudent(input: {name: \"Test User\", email: \"test@example.com\"}) { student { id name email } } }"}' | jq . ``` ### Paso 5: Frontend (opcional) ```bash cd src/frontend # Instalar dependencias (usar --legacy-peer-deps por compatibilidad) npm install --legacy-peer-deps # Iniciar servidor de desarrollo npx ng serve ``` **App Angular:** http://localhost:4200 > **Nota:** Si `ng` no está instalado globalmente, usar `npx ng serve` ## Datos de Ejemplo La migración incluye datos iniciales: | Profesor | Materias | |----------|----------| | Dr. García | Matemáticas I, Matemáticas II | | Dra. López | Física I, Física II | | Ing. Martínez | Programación I, Programación II | | Ing. Rodríguez | Base de Datos I, Base de Datos II | | Ing. Sánchez | Redes I, Redes II | ## Arquitectura ``` Clean Architecture + CQRS + Ports & Adapters ┌─────────────────────────────────────────┐ │ HOST │ │ (DI, Configuration) │ └────────────────┬────────────────────────┘ │ ┌────────────────▼────────────────────────┐ │ ADAPTERS │ │ Driving: GraphQL Driven: EF Core │ └────────────────┬────────────────────────┘ │ ┌────────────────▼────────────────────────┐ │ APPLICATION │ │ Commands / Queries / Validators │ └────────────────┬────────────────────────┘ │ ┌────────────────▼────────────────────────┐ │ DOMAIN │ │ Entities / Value Objects / Ports │ └─────────────────────────────────────────┘ ``` ## Estructura del Proyecto ``` / ├── src/ │ ├── backend/ │ │ ├── Domain/ # Entities, ValueObjects, Ports, Services │ │ ├── Application/ # Commands, Queries, DTOs, Validators │ │ ├── Adapters/ │ │ │ ├── Driving/Api/ # GraphQL (HotChocolate) │ │ │ └── Driven/Persistence/ # EF Core, Repositories, DataLoaders │ │ └── Host/ # Entry point, DI, Configuration │ └── frontend/ │ ├── src/app/ # Core, Shared, Features │ └── e2e/ # Playwright E2E tests ├── tests/ │ ├── Domain.Tests/ # Entity, ValueObject, Service tests │ ├── Application.Tests/ # Command, Query, Validator tests │ └── Integration.Tests/ # End-to-end flow tests ├── docs/ │ ├── entregables/ # 01-analisis, 02-diseno, 03-configuracion │ └── architecture/decisions/ # ADRs ├── database/ │ ├── stored-procedures/ │ └── views/ └── deploy/ ├── docker/ ├── k3s/ # Kubernetes manifests └── scripts/ ``` ## Comandos Útiles ### Backend ```bash cd src/backend # Build y ejecución dotnet build dotnet run --project Host dotnet watch run --project Host # Hot reload # Tests - Todos dotnet test tests/Application.Tests dotnet test tests/Domain.Tests dotnet test tests/Integration.Tests # Tests - Solo Auth dotnet test tests/Application.Tests --filter "FullyQualifiedName~Auth" # Migraciones EF Core dotnet ef migrations add -p Adapters/Driven/Persistence -s Host dotnet ef database update -p Adapters/Driven/Persistence -s Host dotnet ef migrations list -p Adapters/Driven/Persistence -s Host ``` ### Frontend ```bash cd src/frontend npx ng serve # Desarrollo npx ng build --configuration prod # Producción npx ng test # Tests unitarios npx ng lint # Linting # E2E Tests npx playwright test # Todos npx playwright test auth.spec.ts # Solo auth npx playwright test --reporter=html # Con reporte HTML ``` ## Tests Automatizados ### Resumen | Tipo | Cantidad | Estado | |------|----------|--------| | Application Tests | 98 | ✅ 100% | | Domain Tests | 30 | ✅ 100% | | Integration Tests | 5 | ✅ 100% | | E2E Tests | 97 | ⚠️ 26% | | **Total** | **230** | | ### Tests de Auth (Backend) | Handler | Tests | Cobertura | |---------|-------|-----------| | LoginCommand | 6 | Credenciales válidas/inválidas | | RegisterCommand | 8 | Registro, duplicados, validaciones | | ResetPasswordCommand | 8 | Reset válido/inválido | | ActivateAccountCommand | 10 | Activación, expiración, JWT | ### Tests E2E (Playwright) | Categoría | Tests | Descripción | |-----------|-------|-------------| | Autenticación | 15 | Login, registro, reset | | Control de Acceso | 16 | Roles Admin/Student | | Reglas de Negocio | 16 | Max 3 materias, mismo profesor | | Activación | 18 | Flujo completo de activación | | CRUD | 32 | Estudiantes, inscripciones, compañeros | ### Docker ```bash # Ver contenedor SQL Server docker ps | grep sqlserver # Logs docker logs sqlserver # Reiniciar docker restart sqlserver # Conectar con sqlcmd docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P "Asde71.4Asde71.4" -C ``` ## API GraphQL ### Queries ```graphql # Listar estudiantes query { students { id name email totalCredits enrollments { subjectId } } } # Obtener estudiante por ID query { student(id: 1) { id name email totalCredits } } # Listar materias query { subjects { id name credits professorId } } ``` ### Mutations ```graphql # Crear estudiante mutation { createStudent(input: { name: "Juan Pérez", email: "juan@test.com" }) { student { id name email } } } # Inscribir en materia mutation { enrollStudent(input: { studentId: 1, subjectId: 1 }) { enrollment { id } } } # Cancelar inscripción mutation { unenrollStudent(enrollmentId: 1) { success } } ``` ## Solución de Problemas ### `dotnet-ef` no encontrado ```bash # Instalar dotnet tool install --global dotnet-ef # Agregar al PATH (si es necesario) export PATH="$PATH:$HOME/.dotnet/tools" # Verificar instalación dotnet ef --version ``` ### Error de conexión a SQL Server ```bash # Verificar que el contenedor esté corriendo docker ps | grep sqlserver # Si no está, iniciarlo docker start sqlserver # Verificar conexión docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P "Asde71.4Asde71.4" -C -Q "SELECT 1" ``` ### Puerto 5000 en uso ```bash # Linux: encontrar y matar proceso fuser -k 5000/tcp # Alternativa: ver qué usa el puerto lsof -i :5000 kill -9 ``` ### Error "Invalid object name 'Students'" Las migraciones no se han aplicado: ```bash cd src/backend dotnet ef database update -p Adapters/Driven/Persistence -s Host ``` ### Error "No migrations were found" Crear migración inicial: ```bash cd src/backend dotnet ef migrations add InitialCreate -p Adapters/Driven/Persistence -s Host dotnet ef database update -p Adapters/Driven/Persistence -s Host ``` ### Password incorrecto de SQL Server Verificar que el password en `appsettings.json` coincida con el del contenedor Docker: ```json { "ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=StudentEnrollment;User Id=sa;Password=Asde71.4Asde71.4;TrustServerCertificate=True" } } ``` ### Error npm ERESOLVE (conflicto de dependencias) Si aparecen errores de peer dependencies al instalar el frontend: ```bash cd src/frontend rm -rf node_modules package-lock.json npm install --legacy-peer-deps ``` ### Error "ng: command not found" Usar `npx` en lugar del comando directo: ```bash npx ng serve npx ng build ``` ## Despliegue ### Docker Compose (Recomendado) Despliegue optimizado con un solo comando: ```bash cd deploy/docker ./start.sh ``` El script: 1. Limpia contenedores anteriores 2. Construye imágenes optimizadas con cache 3. Inicia todos los servicios 4. Espera hasta que estén listos **URLs después del despliegue:** - Frontend: http://localhost - API GraphQL: http://localhost:5000/graphql - SQL Server: localhost:1433 **Comandos útiles:** ```bash # Ver logs en tiempo real docker compose logs -f # Solo API docker compose logs -f api # Reiniciar un servicio docker compose restart api # Detener todo docker compose down # Rebuild sin cache docker compose build --no-cache && docker compose up -d ``` **Recursos asignados (optimizado para 12 cores / 15GB RAM):** | Servicio | CPU | RAM | |----------|-----|-----| | SQL Server | 2 cores | 2.5 GB | | API .NET | 4 cores | 1.5 GB | | Frontend | 2 cores | 256 MB | ### Kubernetes (k3s) ```bash cd deploy/k3s ./deploy.sh ``` Ver [DEPLOYMENT.md](docs/DEPLOYMENT.md) para instrucciones detalladas. ## Documentación ### Análisis - [Requisitos Funcionales](docs/entregables/01-analisis/requisitos/AN-001-requisitos-funcionales.md) - [Reglas de Negocio](docs/entregables/01-analisis/reglas-negocio/AN-002-reglas-negocio.md) - [Historias de Usuario](docs/entregables/01-analisis/historias-usuario/AN-003-historias-usuario.md) ### Diseño - [Arquitectura Backend](docs/entregables/02-diseno/arquitectura/DI-001-arquitectura-backend.md) - [Arquitectura Frontend](docs/entregables/02-diseno/arquitectura/DI-005-arquitectura-frontend.md) - [Modelo de Dominio](docs/entregables/02-diseno/modelo-dominio/DI-002-modelo-dominio.md) - [Diseño Base de Datos](docs/entregables/02-diseno/base-datos/DI-003-diseno-base-datos.md) - [Esquema GraphQL](docs/entregables/02-diseno/esquema-graphql/DI-004-esquema-graphql.md) ### Configuración - [Configuración .NET](docs/entregables/03-configuracion/DV-002-configuracion-dotnet.md) - [Configuración Angular](docs/entregables/03-configuracion/DV-003-configuracion-angular.md) - [Variables de Entorno](docs/entregables/03-configuracion/DV-005-variables-entorno.md) ### Operaciones - [Manual de Despliegue](docs/DEPLOYMENT.md) - [Decisiones de Arquitectura](docs/architecture/decisions/) - [Checklist OWASP](docs/OWASP_CHECKLIST.md) - [Plan de Actividades](docs/PLAN_ACTIVIDADES.md) ### Diagramas UML - [Casos de Uso](docs/architecture/diagrams/01-use-cases.svg) - [Modelo de Dominio](docs/architecture/diagrams/02-domain-model.svg) - [Secuencia: Inscripción](docs/architecture/diagrams/03-sequence-enrollment.svg) - [Componentes](docs/architecture/diagrams/04-components.svg) - [Entidad-Relación](docs/architecture/diagrams/05-entity-relationship.svg) - [Estados: Inscripción](docs/architecture/diagrams/06-state-enrollment.svg) - [Despliegue](docs/architecture/diagrams/07-deployment.svg) - [C4 Contexto](docs/architecture/diagrams/08-c4-context.svg) ## Autenticación y Roles ### Flujo de Activación de Estudiantes ``` 1. Admin crea estudiante → Sistema genera código de activación (12 chars) 2. Admin comparte código/URL con estudiante 3. Estudiante accede a /activate?code=XXXX 4. Estudiante crea credenciales (usuario + contraseña) 5. Sistema genera código de recuperación (mostrado una sola vez) 6. Estudiante inicia sesión → Dashboard personal ``` ### Roles del Sistema | Rol | Permisos | |-----|----------| | **Admin** | CRUD estudiantes, ver todo, generar códigos de activación | | **Student** | Dashboard personal, inscribir materias, ver compañeros | ### URLs de Autenticación | Ruta | Descripción | |------|-------------| | `/login` | Inicio de sesión | | `/activate?code=XXX` | Activación de cuenta | | `/dashboard` | Dashboard de estudiante | | `/admin` | Panel de administración | ### Seguridad - **JWT** con HMAC-SHA256, expiración configurable - **PBKDF2-SHA256** para hashing de contraseñas (100,000 iteraciones) - **Código de activación:** 12 caracteres, expira en 48 horas - **Código de recuperación:** 12 caracteres, se muestra solo una vez - Input validation con FluentValidation - Sanitización contra XSS - Security headers (CSP, HSTS, X-Frame-Options) - Rate limiting (100 req/min queries, 30 req/min mutations) - Query complexity limits (depth: 5, cost: 100) - Logging estructurado con Serilog (sin datos sensibles) ## Licencia Prueba técnica - Inter Rapidísimo