Saltar al contenido principal

📋 Plan de Ejecución - Módulo 2: Hackathons Module

Fecha de Creación: 2025-01-XX
Estado: 📝 Planificado
Dependencias: ✅ Core Layer, ✅ Users Module


🎯 Objetivo del Módulo

Implementar el CRUD completo de hackathons con:

  • Gestión de estados automáticos (cron job)
  • Validación de fechas estricta
  • Sistema de criterios de evaluación
  • Registro de participantes
  • Panel de organizador

📊 Análisis de Requerimientos

1. Schema Prisma (3 modelos + 1 enum)

Model Hackathon

model Hackathon {
id String @id @default(cuid())
name String
slug String @unique
description String @db.Text
status HackathonStatus @default(DRAFT)

// Fechas (orden estricto requerido)
registrationOpensAt DateTime
registrationClosesAt DateTime
startsAt DateTime
endsAt DateTime
submissionDeadline DateTime
judgingStartsAt DateTime
judgingEndsAt DateTime

// Configuración
maxTeamSize Int @default(5)
minTeamSize Int @default(1)

// Relaciones
participations HackathonParticipation[]
criteria Criterion[]

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@index([slug])
@@index([status])
}

Enum HackathonStatus

enum HackathonStatus {
DRAFT // Borrador, no visible
REGISTRATION // Abierto a registro
RUNNING // En curso
JUDGING // En evaluación
FINISHED // Finalizado
}

Model Criterion

model Criterion {
id String @id @default(cuid())
hackathonId String
name String
description String? @db.Text
weight Int @default(1) // 1-10
maxScore Int @default(10)

hackathon Hackathon @relation(fields: [hackathonId], references: [id], onDelete: Cascade)

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@index([hackathonId])
}

Model HackathonParticipation

model HackathonParticipation {
id String @id @default(cuid())
hackathonId String
profileId String

hackathon Hackathon @relation(fields: [hackathonId], references: [id], onDelete: Cascade)
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)

createdAt DateTime @default(now())

@@unique([hackathonId, profileId])
@@index([hackathonId])
@@index([profileId])
}

2. Funcionalidades Core Requeridas

Queries (4 funciones)

  • getHackathon(slug: string) - Obtener por slug (público)
  • getHackathonById(id: string) - Obtener por ID
  • listHackathons(filters?: { status?: HackathonStatus[] }) - Listar con filtros
  • getOrganizerHackathons(userId: string) - Hackathons de un organizador

Actions (8 Server Actions)

  1. createHackathon(data: CreateHackathonInput)

    • RBAC: ORGANIZER/ADMIN
    • Validar fechas con validateHackathonDates()
    • Crear Hackathon + Criterios en transaction
    • Estado inicial: DRAFT
  2. updateHackathon(id: string, data: UpdateHackathonInput)

    • RBAC: ORGANIZER/ADMIN (owner)
    • Validar fechas
    • Si está en curso, usar validateDateExtension() para extensiones
  3. deleteHackathon(id: string)

    • RBAC: ORGANIZER/ADMIN (owner)
    • Hard delete (cascade en relaciones)
  4. publishHackathon(id: string)

    • RBAC: ORGANIZER/ADMIN (owner)
    • Validar: tiene criterios, tiene jueces, now >= registrationOpensAt
    • Cambiar estado: DRAFT → REGISTRATION
  5. registerForHackathon(hackathonId: string)

    • RBAC: PARTICIPANT
    • Validar: estado REGISTRATION, fechas válidas, no duplicado
    • Crear HackathonParticipation
  6. unregisterFromHackathon(hackathonId: string)

    • RBAC: PARTICIPANT
    • Eliminar HackathonParticipation
  7. addCriterion(hackathonId: string, data: CriterionInput)

    • RBAC: ORGANIZER/ADMIN (owner)
    • Crear Criterion
  8. updateCriterion(id: string, data: CriterionInput)

    • RBAC: ORGANIZER/ADMIN (owner del hackathon)
    • Actualizar Criterion
  9. deleteCriterion(id: string)

    • RBAC: ORGANIZER/ADMIN (owner del hackathon)
    • Eliminar Criterion

Validations (Zod Schemas)

  • createHackathonSchema - Validar creación
  • updateHackathonSchema - Validar actualización
  • criterionSchema - Validar criterio
  • Integración con validateHackathonDates() y validateDateExtension()

Cron Job

  • src/app/api/cron/update-hackathon-states/route.ts
  • Cambiar estados automáticamente cada minuto
  • Solo hackathons publicados (no DRAFT)

3. UI Funcional (5 páginas)

  1. /hackathons - Lista pública

    • Server Component
    • Filtro por status
    • Mostrar hackathons publicados
  2. /hackathons/[slug] - Detalle público

    • Server Component
    • Información completa del hackathon
    • Botón "Registrarse" (si PARTICIPANT y REGISTRATION)
  3. /admin/hackathons/create - Crear hackathon

    • Formulario HTML + Server Action
    • Campos: name, slug, description, fechas, criterios
    • Validación en servidor
  4. /admin/hackathons/[slug] - Editar hackathon

    • Formulario pre-llenado
    • Server Action actualiza
    • Soporte para extensiones de fechas
  5. /admin/hackathons/[slug]/dashboard - Panel organizador

    • Stats: participantes, equipos, submissions
    • Lista de participantes

🗂️ Plan de Ejecución por Fases

FASE 1: Schema y Migración (Prioridad: CRÍTICA)

Objetivo: Definir y migrar el schema de base de datos

Tareas:

  1. ✅ Actualizar prisma/schema.prisma

    • Agregar enum HackathonStatus
    • Agregar model Hackathon con todos los campos
    • Agregar model Criterion
    • Agregar model HackathonParticipation
    • Definir relaciones y índices
    • Agregar onDelete: Cascade donde corresponda
  2. ✅ Ejecutar migración

    pnpm prisma migrate dev --name add_hackathons_module
  3. ✅ Verificar schema en Prisma Studio

    pnpm prisma studio

Criterio de Completitud:

  • Schema completo y sin errores
  • Migración ejecutada exitosamente
  • Relaciones funcionando correctamente

Tiempo Estimado: 30-45 minutos


FASE 2: Module Files - Core (Prioridad: CRÍTICA)

Objetivo: Implementar la lógica core del módulo (queries, validations, types)

2.1 Types (src/modules/hackathons/types.ts)

Tareas:

  1. Definir tipos TypeScript
    • HackathonWithRelations (con criterios, participaciones)
    • CreateHackathonInput
    • UpdateHackathonInput
    • CriterionInput
    • HackathonFilters

Criterio de Completitud:

  • Todos los tipos exportados
  • Tipos usados en queries/actions

Tiempo Estimado: 15 minutos

2.2 Validations (src/modules/hackathons/validations.ts)

Tareas:

  1. Crear createHackathonSchema (Zod)

    • name, slug, description
    • Fechas (usar hackathonDatesSchema de core/validations.ts)
    • maxTeamSize, minTeamSize
    • Criterios (array opcional)
  2. Crear updateHackathonSchema (Zod)

    • Campos opcionales
    • Validación de fechas
  3. Crear criterionSchema (Zod)

    • name, description, weight (1-10), maxScore
  4. Crear publishHackathonSchema (Zod)

    • Validar que tiene criterios y jueces

Criterio de Completitud:

  • Todos los schemas creados
  • Integración con validateHackathonDates() funcionando
  • Tests de validaciones pasando

Tiempo Estimado: 45 minutos

2.3 Queries (src/modules/hackathons/queries.ts)

Tareas:

  1. Implementar getHackathon(slug: string)

    • Incluir criterios y participaciones
    • Retornar null si no existe
  2. Implementar getHackathonById(id: string)

    • Similar a getHackathon pero por ID
  3. Implementar listHackathons(filters?: { status?: HackathonStatus[] })

    • Filtro por status
    • Ordenar por createdAt desc
    • Incluir criterios count
  4. Implementar getOrganizerHackathons(userId: string)

    • Obtener hackathons donde el usuario es organizador
    • Incluir stats básicas

Criterio de Completitud:

  • Todas las queries implementadas
  • Tests de queries pasando (100% coverage)

Tiempo Estimado: 1 hora


FASE 3: Actions - CRUD Básico (Prioridad: ALTA)

Objetivo: Implementar acciones básicas de CRUD

3.1 createHackathon

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN)
  2. Validar datos con Zod
  3. Validar fechas con validateHackathonDates()
  4. Crear Hackathon + Criterios en transaction
  5. Revalidar cache
  6. Retornar hackathon creado

Criterio de Completitud:

  • RBAC funcionando
  • Validación de fechas funcionando
  • Transaction funcionando
  • Test pasando

Tiempo Estimado: 1 hora

3.2 updateHackathon

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner)
  2. Validar datos con Zod
  3. Si está en curso, usar validateDateExtension()
  4. Si no está en curso, usar validateHackathonDates()
  5. Actualizar hackathon
  6. Revalidar cache

Criterio de Completitud:

  • RBAC funcionando
  • Validación de extensiones funcionando
  • Test pasando

Tiempo Estimado: 1 hora

3.3 deleteHackathon

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner)
  2. Verificar que no tiene participaciones activas (opcional, o permitir cascade)
  3. Eliminar hackathon (cascade elimina criterios y participaciones)
  4. Revalidar cache

Criterio de Completitud:

  • RBAC funcionando
  • Cascade funcionando
  • Test pasando

Tiempo Estimado: 30 minutos


FASE 4: Actions - Criterios (Prioridad: ALTA)

Objetivo: Implementar gestión de criterios

4.1 addCriterion

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner)
  2. Validar datos con Zod
  3. Verificar que hackathon existe
  4. Crear criterio
  5. Revalidar cache

Tiempo Estimado: 30 minutos

4.2 updateCriterion

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner del hackathon)
  2. Validar datos con Zod
  3. Actualizar criterio
  4. Revalidar cache

Tiempo Estimado: 30 minutos

4.3 deleteCriterion

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner del hackathon)
  2. Eliminar criterio
  3. Revalidar cache

Tiempo Estimado: 20 minutos

Criterio de Completitud Fase 4:

  • Todas las acciones de criterios funcionando
  • Tests pasando

FASE 5: Actions - Participaciones (Prioridad: ALTA)

Objetivo: Implementar registro/desregistro de participantes

5.1 registerForHackathon

Tareas:

  1. Validar RBAC (PARTICIPANT)
  2. Verificar estado: REGISTRATION
  3. Verificar fechas: now >= registrationOpensAt && now <= registrationClosesAt
  4. Verificar que no está registrado
  5. Crear HackathonParticipation
  6. Revalidar cache

Tiempo Estimado: 45 minutos

5.2 unregisterFromHackathon

Tareas:

  1. Validar RBAC (PARTICIPANT)
  2. Verificar que está registrado
  3. Eliminar HackathonParticipation
  4. Revalidar cache

Tiempo Estimado: 30 minutos

Criterio de Completitud Fase 5:

  • Registro funcionando
  • Desregistro funcionando
  • Validaciones funcionando
  • Tests pasando

FASE 6: Action - Publicar Hackathon (Prioridad: ALTA)

Objetivo: Implementar publicación manual de hackathons

6.1 publishHackathon

Tareas:

  1. Validar RBAC (ORGANIZER/ADMIN owner)
  2. Verificar que tiene al menos 1 criterio
  3. Verificar que tiene al menos 1 juez (HackathonJudge - se implementará en módulo futuro, por ahora solo validar criterios)
  4. Verificar que now >= registrationOpensAt
  5. Cambiar estado: DRAFT → REGISTRATION
  6. Revalidar cache

Nota: La validación de jueces se puede hacer más adelante cuando se implemente el módulo de jueces. Por ahora, solo validar criterios.

Tiempo Estimado: 30 minutos

Criterio de Completitud:

  • Publicación funcionando
  • Validaciones funcionando
  • Test pasando

FASE 7: Cron Job (Prioridad: ALTA)

Objetivo: Implementar cambios automáticos de estado

7.1 API Route del Cron

Tareas:

  1. Crear src/app/api/cron/update-hackathon-states/route.ts
  2. Validar CRON_SECRET en headers
  3. Implementar lógica de cambios de estado:
    • REGISTRATION → RUNNING (cuando now >= registrationClosesAt)
    • RUNNING → JUDGING (cuando now >= judgingStartsAt)
    • JUDGING → FINISHED (cuando now >= judgingEndsAt)
  4. Solo procesar hackathons publicados (no DRAFT)
  5. Retornar estadísticas de actualizaciones

Tiempo Estimado: 45 minutos

7.2 Configuración Vercel

Tareas:

  1. Crear vercel.json con configuración de cron
  2. Agregar CRON_SECRET a .env.local
  3. Documentar configuración

Tiempo Estimado: 15 minutos

Criterio de Completitud:

  • Cron funcionando
  • Configuración lista
  • Test manual funcionando

FASE 8: Testing (Prioridad: CRÍTICA)

Objetivo: Asegurar calidad y cobertura

8.1 Tests de Queries

Tareas:

  1. Test getHackathon (existe, no existe)
  2. Test getHackathonById (existe, no existe)
  3. Test listHackathons (sin filtros, con filtros)
  4. Test getOrganizerHackathons

Tiempo Estimado: 1 hora

8.2 Tests de Actions

Tareas:

  1. Tests de createHackathon (éxito, RBAC, validación fechas)
  2. Tests de updateHackathon (éxito, RBAC, extensiones)
  3. Tests de deleteHackathon (éxito, RBAC)
  4. Tests de publishHackathon (éxito, validaciones)
  5. Tests de registerForHackathon (éxito, validaciones)
  6. Tests de unregisterFromHackathon (éxito, RBAC)
  7. Tests de criterios (add, update, delete)

Tiempo Estimado: 2 horas

8.3 Tests de Validations

Tareas:

  1. Tests de createHackathonSchema
  2. Tests de updateHackathonSchema
  3. Tests de criterionSchema
  4. Tests de validación de fechas

Tiempo Estimado: 1 hora

Criterio de Completitud:

  • Coverage >80%
  • Todos los tests pasando
  • Tests de RBAC completos

FASE 9: UI - Páginas Públicas (Prioridad: MEDIA)

Objetivo: Implementar vistas públicas de hackathons

9.1 /hackathons - Lista Pública

Tareas:

  1. Crear Server Component
  2. Obtener hackathons publicados (REGISTRATION, RUNNING, JUDGING, FINISHED)
  3. Filtro por status (Client Component mínimo)
  4. Mostrar lista con información básica
  5. Links a detalle

Tiempo Estimado: 1 hora

9.2 /hackathons/[slug] - Detalle Público

Tareas:

  1. Crear Server Component
  2. Obtener hackathon por slug
  3. Mostrar información completa
  4. Botón "Registrarse" (si PARTICIPANT y REGISTRATION)
  5. Server Action para registro

Tiempo Estimado: 1 hora

Criterio de Completitud:

  • Lista funcionando
  • Detalle funcionando
  • Registro funcionando

FASE 10: UI - Panel de Organizador (Prioridad: ALTA)

Objetivo: Implementar gestión de hackathons para organizadores

10.1 /admin/hackathons/create - Crear Hackathon

Tareas:

  1. Crear Server Component
  2. Formulario HTML con campos:
    • name, slug, description
    • Fechas (7 campos datetime-local)
    • maxTeamSize, minTeamSize
    • Criterios (array dinámico)
  3. Server Action createHackathon
  4. Validación en servidor
  5. Redirección después de crear

Tiempo Estimado: 2 horas

10.2 /admin/hackathons/[slug] - Editar Hackathon

Tareas:

  1. Crear Server Component
  2. Obtener hackathon por slug
  3. Formulario pre-llenado
  4. Server Action updateHackathon
  5. Soporte para extensiones de fechas (si está en curso)
  6. Validación en servidor

Tiempo Estimado: 1.5 horas

10.3 /admin/hackathons/[slug]/dashboard - Panel Organizador

Tareas:

  1. Crear Server Component
  2. Obtener stats:
    • Total participantes
    • Total equipos (futuro, por ahora 0)
    • Total submissions (futuro, por ahora 0)
  3. Lista de participantes
  4. Acciones: ver perfil, eliminar participación

Tiempo Estimado: 1.5 horas

Criterio de Completitud:

  • Crear funcionando
  • Editar funcionando
  • Dashboard funcionando
  • Validaciones funcionando

📐 Orden de Ejecución Recomendado

Secuencia Lógica:

  1. FASE 1: Schema y Migración ⚡ (CRÍTICA)
  2. FASE 2: Module Files Core (Types, Validations, Queries) ⚡ (CRÍTICA)
  3. FASE 3: Actions CRUD Básico (create, update, delete) ⚡ (ALTA)
  4. FASE 4: Actions Criterios ⚡ (ALTA)
  5. FASE 5: Actions Participaciones ⚡ (ALTA)
  6. FASE 6: Action Publicar ⚡ (ALTA)
  7. FASE 7: Cron Job ⚡ (ALTA)
  8. FASE 8: Testing ⚡ (CRÍTICA)
  9. FASE 9: UI Páginas Públicas (MEDIA)
  10. FASE 10: UI Panel Organizador (ALTA)

Regla de Oro:

NO avanzar a la siguiente fase hasta que la anterior esté 100% completa y testeada.


✅ Criterios de Completitud por Fase

Fase 1 - Schema

  • Schema completo sin errores
  • Migración ejecutada
  • Relaciones funcionando

Fase 2 - Module Files Core

  • Types exportados
  • Validations con tests pasando
  • Queries con tests pasando (100% coverage)

Fase 3-6 - Actions

  • Cada action con RBAC funcionando
  • Validaciones funcionando
  • Tests pasando

Fase 7 - Cron Job

  • Cron funcionando
  • Configuración lista
  • Test manual exitoso

Fase 8 - Testing

  • Coverage >80%
  • Todos los tests pasando
  • Tests de RBAC completos

Fase 9-10 - UI

  • Todas las páginas funcionando
  • Validaciones en servidor funcionando
  • Navegación funcionando

🎯 Principios de Implementación

1. Modularidad

  • Cada archivo con responsabilidad única
  • Separación clara: queries, actions, validations, types
  • Reutilización de helpers de core/

2. Profesionalismo

  • Código limpio y bien documentado
  • Nombres descriptivos
  • Manejo de errores consistente
  • Patrones consistentes con Módulo 1

3. Seguridad

  • RBAC en cada Server Action
  • Validación en servidor (nunca confiar en cliente)
  • Validación de ownership (ORGANIZER solo puede editar sus hackathons)

4. Testing

  • Tests antes de UI (TDD cuando sea posible)
  • Coverage >80%
  • Tests de RBAC exhaustivos
  • Tests de validaciones de fechas

5. UI

  • Server Components por defecto
  • Client Components solo cuando necesario
  • Actualizaciones optimistas donde aplique
  • Formularios HTML nativos + Server Actions

📝 Notas Importantes

Validación de Fechas

  • SIEMPRE usar validateHackathonDates() en creación
  • SIEMPRE usar validateDateExtension() en actualizaciones de hackathons en curso
  • El orden es estricto y no negociable

Estados del Hackathon

  • DRAFT: No visible públicamente
  • REGISTRATION: Visible, abierto a registro
  • RUNNING: En curso, no se puede registrar
  • JUDGING: En evaluación
  • FINISHED: Finalizado

Cron Job

  • Solo procesa hackathons publicados (no DRAFT)
  • Se ejecuta cada minuto
  • Cambios de estado son automáticos e irreversibles (excepto por ADMIN)

Ownership

  • ORGANIZER solo puede gestionar hackathons que creó
  • ADMIN puede gestionar todos los hackathons
  • Validar ownership en cada action

⏱️ Estimación Total

Tiempo Total Estimado: 12-15 horas

Desglose:

  • Schema: 30-45 min
  • Module Files Core: 2 horas
  • Actions: 5 horas
  • Cron Job: 1 hora
  • Testing: 4 horas
  • UI: 5 horas

🚀 Siguiente Paso

Comenzar con FASE 1: Schema y Migración

¿Procedemos con la implementación siguiendo este plan?