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

5.9 KiB

DI-004: Esquema GraphQL

Proyecto: Sistema de Registro de Estudiantes Fecha: 2026-01-07


1. Schema Completo

# ═══════════════════════════════════════════════════════════════
# 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

query GetStudents {
  students {
    id
    name
    email
    totalCredits
    enrollments {
      subject { name professor { name } }
    }
  }
}

Materias disponibles para inscripción

query GetAvailableSubjects($studentId: Int!) {
  availableSubjects(studentId: $studentId) {
    subject { id name credits professor { name } }
    isAvailable
    unavailableReason
  }
}

Compañeros de clase

query GetClassmates($studentId: Int!) {
  classmates(studentId: $studentId) {
    subjectName
    students
  }
}

3. Ejemplos de Mutations

Crear estudiante

mutation CreateStudent {
  createStudent(input: { name: "Juan Pérez", email: "juan@email.com" }) {
    student { id name email }
    errors
  }
}

Inscribir en materia

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