academia/docs/entregables/02-diseno/esquema-graphql/DI-004-esquema-graphql.md

227 lines
5.9 KiB
Markdown

# DI-004: Esquema GraphQL
**Proyecto:** Sistema de Registro de Estudiantes
**Fecha:** 2026-01-07
---
## 1. Schema Completo
```graphql
# ═══════════════════════════════════════════════════════════════
# TYPES
# ═══════════════════════════════════════════════════════════════
type Student {
id: Int!
name: String!
email: String!
totalCredits: Int!
enrollments: [Enrollment!]!
}
type Subject {
id: Int!
name: String!
credits: Int!
professor: Professor!
enrolledStudents: [Student!]!
}
type Professor {
id: Int!
name: String!
subjects: [Subject!]!
}
type Enrollment {
id: Int!
student: Student!
subject: Subject!
enrolledAt: DateTime!
}
type AvailableSubject {
subject: Subject!
isAvailable: Boolean!
unavailableReason: String
}
type Classmate {
subjectName: String!
students: [String!]!
}
# ═══════════════════════════════════════════════════════════════
# QUERIES
# ═══════════════════════════════════════════════════════════════
type Query {
# Estudiantes
students: [Student!]!
student(id: Int!): Student
# Materias
subjects: [Subject!]!
subject(id: Int!): Subject
availableSubjects(studentId: Int!): [AvailableSubject!]!
# Profesores
professors: [Professor!]!
professor(id: Int!): Professor
# Compañeros de clase
classmates(studentId: Int!): [Classmate!]!
}
# ═══════════════════════════════════════════════════════════════
# MUTATIONS
# ═══════════════════════════════════════════════════════════════
type Mutation {
# Estudiantes
createStudent(input: CreateStudentInput!): StudentPayload!
updateStudent(id: Int!, input: UpdateStudentInput!): StudentPayload!
deleteStudent(id: Int!): DeletePayload!
# Inscripciones
enrollStudent(input: EnrollInput!): EnrollmentPayload!
unenrollStudent(enrollmentId: Int!): DeletePayload!
}
# ═══════════════════════════════════════════════════════════════
# INPUTS
# ═══════════════════════════════════════════════════════════════
input CreateStudentInput {
name: String!
email: String!
}
input UpdateStudentInput {
name: String
email: String
}
input EnrollInput {
studentId: Int!
subjectId: Int!
}
# ═══════════════════════════════════════════════════════════════
# PAYLOADS (Union para errores)
# ═══════════════════════════════════════════════════════════════
type StudentPayload {
student: Student
errors: [String!]
}
type EnrollmentPayload {
enrollment: Enrollment
errors: [String!]
}
type DeletePayload {
success: Boolean!
errors: [String!]
}
# ═══════════════════════════════════════════════════════════════
# SCALARS
# ═══════════════════════════════════════════════════════════════
scalar DateTime
```
---
## 2. Ejemplos de Queries
### Listar estudiantes con inscripciones
```graphql
query GetStudents {
students {
id
name
email
totalCredits
enrollments {
subject { name professor { name } }
}
}
}
```
### Materias disponibles para inscripción
```graphql
query GetAvailableSubjects($studentId: Int!) {
availableSubjects(studentId: $studentId) {
subject { id name credits professor { name } }
isAvailable
unavailableReason
}
}
```
### Compañeros de clase
```graphql
query GetClassmates($studentId: Int!) {
classmates(studentId: $studentId) {
subjectName
students
}
}
```
---
## 3. Ejemplos de Mutations
### Crear estudiante
```graphql
mutation CreateStudent {
createStudent(input: { name: "Juan Pérez", email: "juan@email.com" }) {
student { id name email }
errors
}
}
```
### Inscribir en materia
```graphql
mutation Enroll {
enrollStudent(input: { studentId: 1, subjectId: 3 }) {
enrollment {
id
subject { name }
enrolledAt
}
errors
}
}
```
---
## 4. DataLoaders (Evitar N+1)
| DataLoader | Carga Batch |
|------------|-------------|
| `StudentByIdDataLoader` | Estudiantes por IDs |
| `SubjectByIdDataLoader` | Materias por IDs |
| `ProfessorByIdDataLoader` | Profesores por IDs |
| `EnrollmentsByStudentDataLoader` | Inscripciones por estudiante |
| `SubjectsByProfessorDataLoader` | Materias por profesor |
---
## 5. Errores de Negocio
| Código | Mensaje | Contexto |
|--------|---------|----------|
| `MAX_ENROLLMENTS` | "Máximo 3 materias permitidas" | enrollStudent |
| `SAME_PROFESSOR` | "Ya tienes materia con este profesor" | enrollStudent |
| `DUPLICATE_EMAIL` | "Email ya registrado" | createStudent |
| `NOT_FOUND` | "Estudiante no encontrado" | updateStudent |