Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
name: Deploy API
name: CI

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

jobs:
deploy:
ci:
runs-on: ubuntu-latest
env:
USE_SQLITE: "true"
DJANGO_SECRET_KEY: ci-only-secret-key
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -28,11 +32,10 @@ jobs:
working-directory: ./bedelia
run: |
python manage.py check
python manage.py test || echo "No tests configured yet"
python manage.py test

- name: Lint with flake8
working-directory: ./bedelia
run: |
pip install flake8
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics || true

flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
153 changes: 54 additions & 99 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,188 +2,143 @@

Guía rápida para poner en marcha los modelos y cargar datos en menos de 5 minutos.

## 🚀 Inicio Rápido (3 comandos)
Todos los comandos se ejecutan desde el directorio `bedelia/` (donde está `manage.py`).
Con `USE_SQLITE=true` no hace falta PostgreSQL.

## 🚀 Inicio Rápido

```bash
# 1. Crear y aplicar migraciones
python manage.py makemigrations
python manage.py migrate
cd bedelia

# 1. Aplicar migraciones
USE_SQLITE=true python manage.py migrate

# 2. Verificar con dry-run (opcional pero recomendado)
python manage.py load_bedelia_data --dry-run
USE_SQLITE=true python manage.py load_bedelia_data --dry-run

# 3. Cargar datos
python manage.py load_bedelia_data --clear --verbose
USE_SQLITE=true python manage.py load_bedelia_data --clear --verbose
```

¡Listo! 🎉

---

## 📋 Lo que acabas de crear
## 📋 Modelos principales

```
Estructura de Base de Datos:
├── carreras (45 registros aprox)
├── cursos (1,200+ registros)
├── previas (5,000+ nodos de árbol)
├── items_previa (10,000+ items)
└── posprevias (8,000+ relaciones)
api/models.py:
├── PlanEstudio (carrera + año del plan)
├── Materia (curso con código y créditos)
├── PlanMateria (materia dentro de un plan)
├── UnidadAprobable (curso / examen / módulo aprobable)
├── PreviaNodo (árbol lógico de previas: ALL / ANY / NOT / LEAF)
├── PreviaItem (condición concreta de un nodo LEAF)
└── PosPreviaItem (dependencias inversas: qué requiere esta materia)
```

---

## 🧪 Verificar que funciona

```bash
python manage.py shell
USE_SQLITE=true python manage.py shell
```

```python
from api.models import Carrera, Curso, Previa
from api.models import PlanEstudio, Materia, PreviaNodo

# Ver totales
print(f"Carreras: {Carrera.objects.count()}")
print(f"Cursos: {Curso.objects.count()}")
print(f"Previas: {Previa.objects.count()}")
print(f"Planes de estudio: {PlanEstudio.objects.count()}")
print(f"Materias: {Materia.objects.count()}")
print(f"Nodos de previas: {PreviaNodo.objects.count()}")

# Ver ejemplo
curso = Curso.objects.first()
print(f"\nEjemplo: {curso}")
print(f"Créditos: {curso.creditos}")
print(f"Carreras: {curso.carrera.count()}")
```

**Salida esperada:**
```
Carreras: 45
Cursos: 1234
Previas: 5678

Ejemplo: 1267 - TALLER REPR. Y COM. GRAFICA
Créditos: 5
Carreras: 2
materia = Materia.objects.first()
print(f"\nEjemplo: {materia}")
print(f"Créditos: {materia.creditos}")
```

---

## 📚 Consultas Útiles
## 📚 Consultas útiles

### Ver todas las carreras
### Ver planes de estudio
```python
from api.models import Carrera
for c in Carrera.objects.all()[:10]:
print(f"- {c.nombre} ({c.anio_plan})")
from api.models import PlanEstudio
for p in PlanEstudio.objects.all()[:10]:
print(f"- {p.nombre_carrera} ({p.anio})")
```

### Buscar un curso
### Buscar una materia
```python
from api.models import Curso
curso = Curso.objects.filter(codigo_curso="1144").first()
print(curso.nombre_curso)
print(f"Créditos: {curso.creditos}")
from api.models import Materia
materia = Materia.objects.filter(codigo="1144").first()
print(materia.nombre, materia.creditos)
```

### Ver árbol de previas
### Ver nodos raíz del árbol de previas
```python
curso = Curso.objects.get(codigo_curso="1144")
previas_raiz = curso.previas.filter(padre__isnull=True)
for previa in previas_raiz:
print(f"Tipo: {previa.tipo}")
print(f"Título: {previa.titulo}")
from api.models import PreviaNodo
for nodo in PreviaNodo.objects.filter(padre__isnull=True)[:5]:
print(f"Tipo: {nodo.tipo} - {nodo.descripcion}")
```

### Ver posprevias (qué materias requieren este curso)
```python
curso = Curso.objects.get(codigo_curso="1061")
posprevias = curso.posprevias.all()[:5]
for p in posprevias:
print(f"- {p.materia_nombre}")
from api.models import Materia
materia = Materia.objects.filter(codigo="1061").first()
for p in materia.posprevias.all()[:5]:
print(f"- {p.plan_estudio}: {p.descripcion}")
```

---

## 🎯 Datos Clave

### Estructura de Archivos JSON
### Estructura de Archivos JSON (en `../data/`)

- ✅ **vigentes**: TODOS los cursos activos
- ✅ **credits**: Créditos de los cursos
- ✅ **credits**: Créditos de los cursos
- ⚠️ **previas**: Solo cursos CON requisitos (NO todos)
- ✅ **posprevias**: Dependencias inversas

### Es Normal

✅ Que haya cursos sin previas
✅ Que el proceso tome 3-5 minutos
✅ Ver advertencias sobre cursos no encontrados

### NO es Normal

❌ Que todos los cursos tengan previas
❌ Errores de base de datos
❌ Que falten archivos JSON

---

## 🔄 Actualizar Datos

```bash
# Borrar todo y recargar
python manage.py load_bedelia_data --clear

# Actualización incremental (solo nuevos/modificados)
python manage.py load_bedelia_data
```
✅ Que haya cursos sin previas
✅ Que el proceso tome 3-5 minutos
✅ Ver advertencias sobre cursos no encontrados

---

## 🐛 Problemas Comunes

### "Archivo no encontrado"
```bash
# Verificar que los archivos existan
ls data/*.json
# Los JSON viven en data/ en la raíz del repo
ls ../data/*.json
```

### "Out of memory"
- Usar PostgreSQL en lugar de SQLite
- Aumentar memoria disponible
- Cerrar otras aplicaciones

### "Integrity error"
```bash
# Limpiar y reintentar
python manage.py load_bedelia_data --clear
USE_SQLITE=true python manage.py load_bedelia_data --clear
```

---

## 📖 Más Información

- [SETUP_GUIDE.md](SETUP_GUIDE.md) - Guía completa paso a paso
- [CHANGELOG_MODELS.md](CHANGELOG_MODELS.md) - Detalles de implementación
- [bedelia/api/ESTRUCTURA_MODELOS.md](bedelia/api/ESTRUCTURA_MODELOS.md) - Documentación de modelos
- [bedelia/api/management/commands/README_load_bedelia_data.md](bedelia/api/management/commands/README_load_bedelia_data.md) - Documentación del comando

---

## 🆘 Ayuda Rápida

```bash
# Ver ayuda del comando
python manage.py load_bedelia_data --help

# Probar sin guardar
python manage.py load_bedelia_data --dry-run --verbose

# Ver qué se cargó
python manage.py shell < bedelia/api/management/commands/verify_data.py
USE_SQLITE=true python manage.py load_bedelia_data --dry-run --verbose
```

---

**¡Ya estás listo para usar la API! 🚀**

Siguiente paso: Crear serializers y endpoints REST → Ver [TODO.md](TODO.md)

Con el servidor corriendo (`python manage.py runserver`), la documentación interactiva está en `/api/docs/` y hay una colección de Postman en la raíz del repo.
Loading
Loading