Volver a proyectos
Web
1 min de lectura

Plataforma del Departamento de Educación de Puerto Rico

Por Jeferson Heredia
13 de julio de 2025
WordPress
Migración Web
Diseño UI/UX
Accesibilidad
Sitio Gubernamental
Educación
Plataforma del Departamento de Educación de Puerto Rico

Descripción

Lideré el desarrollo completo y rediseño del sitio web oficial del Departamento de Educación de Puerto Rico (DEPR), una institución gubernamental clave responsable de la educación pública en todo Puerto Rico.

Este proyecto representó un desafío significativo ya que requirió trabajar en la nueva plataforma mientras simultáneamente se mantenía y actualizaba la versión anterior que estaba en producción. La migración desde el tema Avada a una solución WordPress personalizada implicó la transferencia cuidadosa de grandes volúmenes de contenido educativo, recursos para docentes, información administrativa y datos históricos.

La nueva plataforma fue diseñada con un enfoque en la accesibilidad, asegurando que todos los usuarios, incluidas las personas con discapacidades, pudieran acceder fácilmente a la información educativa crítica. Implementé características avanzadas como un sistema de búsqueda mejorado, integración con aplicaciones internas del departamento, y una arquitectura de información optimizada para facilitar la navegación a través de los numerosos programas y servicios ofrecidos por el DEPR.

El sitio también incorpora funcionalidades específicas para el sector educativo, como calendarios académicos interactivos, directorios de escuelas, acceso a recursos educativos digitales, y sistemas de citas en línea para servicios administrativos, todo ello manteniendo altos estándares de seguridad y cumplimiento con las normativas gubernamentales.

Tecnologías Utilizadas

WordPress

CMS principal para el desarrollo y gestión de contenidos

PHP

Desarrollo de funcionalidades personalizadas y plugins específicos

MySQL

Base de datos optimizada para alto rendimiento y seguridad

JavaScript

Interactividad y mejoras de experiencia de usuario

HTML5/CSS3

Maquetación semántica y diseño responsivo accesible

WCAG 2.1

Implementación de estándares de accesibilidad web

Desafíos

Desarrollo paralelo

Trabajar en la nueva plataforma mientras simultáneamente se mantenía y actualizaba la versión anterior en producción, garantizando la continuidad del servicio para estudiantes, padres y educadores.

Migración desde Avada

Migrar grandes volúmenes de contenido desde el tema Avada a una solución WordPress personalizada, preservando la integridad de los datos y la estructura de la información.

Accesibilidad universal

Asegurar que el sitio cumpliera con estrictos estándares de accesibilidad para servir a todos los ciudadanos, incluyendo personas con diversas discapacidades.

Integración de sistemas

Integrar el sitio web con múltiples aplicaciones internas y sistemas del departamento de educación, manteniendo la seguridad y la coherencia de los datos.

Soluciones

Estrategia de migración por fases

Implementé un enfoque de migración gradual que permitió transferir y validar el contenido por secciones, minimizando el riesgo y asegurando la continuidad del servicio.

Desarrollo de tema personalizado

Creé un tema WordPress completamente personalizado que se adaptaba exactamente a las necesidades específicas del departamento, superando las limitaciones del tema Avada anterior.

Implementación WCAG 2.1

Desarrollé el sitio siguiendo rigurosamente las pautas WCAG 2.1 nivel AA, incluyendo navegación por teclado, compatibilidad con lectores de pantalla y contraste de color adecuado.

Arquitectura de API

Diseñé una arquitectura de API robusta que permite la comunicación segura entre el sitio web público y los sistemas internos del departamento, facilitando la integración de servicios.

Galería

Página principal del Departamento de Educación de Puerto Rico

Página principal del Departamento de Educación de Puerto Rico

Versión móvil optimizada del sitio

Versión móvil optimizada del sitio

Sección de servicios educativos

Sección de servicios educativos

Ejemplo de Código

user_manager.py

from django.db import models
from django.contrib.auth.models import User
from django.utils.text import slugify
from django.urls import reverse
import uuid

class Category(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    description = models.TextField(blank=True)
    
    class Meta:
        verbose_name_plural = "Categories"
        
    def __str__(self):
        return self.name
        
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)

class Product(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="products")
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField(default=0)
    available = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='products/', blank=True, null=True)
    featured = models.BooleanField(default=False)
    
    class Meta:
        ordering = ['-created_at']
        
    def __str__(self):
        return self.name
        
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)
        
    def get_absolute_url(self):
        return reverse('product_detail', kwargs={'slug': self.slug})
        
    @property
    def is_in_stock(self):
        return self.stock > 0

class Order(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('processing', 'Processing'),
        ('shipped', 'Shipped'),
        ('delivered', 'Delivered'),
        ('cancelled', 'Cancelled'),
    )
    
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="orders")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    shipping_address = models.TextField()
    total_amount = models.DecimalField(max_digits=10, decimal_places=2)
    
    def __str__(self):
        return f"Order {self.id} - {self.user.username}"
        
    @property
    def order_items(self):
        return self.items.all()
        
    @property
    def item_count(self):
        return sum(item.quantity for item in self.order_items)

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="items")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    
    def __str__(self):
        return f"{self.quantity} x {self.product.name}"
        
    @property
    def total_price(self):
        return self.price * self.quantity

# Views example (in views.py)
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView
from .models import Product, Category

class ProductListView(ListView):
    model = Product
    template_name = 'shop/product_list.html'
    context_object_name = 'products'
    paginate_by = 12
    
    def get_queryset(self):
        queryset = Product.objects.filter(available=True)
        category_slug = self.kwargs.get('category_slug')
        
        if category_slug:
            category = get_object_or_404(Category, slug=category_slug)
            queryset = queryset.filter(category=category)
            
        return queryset
        
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        return context

class ProductDetailView(DetailView):
    model = Product
    template_name = 'shop/product_detail.html'
    context_object_name = 'product'
    slug_url_kwarg = 'slug'

Compartir

Habilidades Python

Python Core
Data Analysis
Web Frameworks
Machine Learning
Testing

¿Interesado en un proyecto similar?

Si estás buscando implementar una solución en Python o tienes un proyecto en mente que requiera habilidades de desarrollo similares, no dudes en contactarme para discutir cómo puedo ayudarte.

Contactar