Skip to main content

Overview

The Project Management module handles capital projects (CAPEX), improvement initiatives, and multi-activity work with dependency tracking, Gantt visualization, and AI-powered assistance.

Key Features

Project Tracking

Create and monitor projects with activities

Dependencies

Define predecessor relationships between activities

Gantt Chart

Visual timeline with critical path

AI Assistant

Gemini-powered project assistant for Q&A

Data Model

Proyecto (Project)

proyectos/models.py
class Proyecto(models.Model):
    ESTADOS = [
        ('PLANEACION', 'Planeación'),
        ('EN_CURSO', 'En Curso'),
        ('SUSPENDIDO', 'Suspendido'),
        ('COMPLETADO', 'Completado'),
        ('CANCELADO', 'Cancelado'),
    ]
    
    # Auto-generated code: PROY-YYYY-NNNN
    codigo = models.CharField(max_length=50, unique=True)
    nombre = models.CharField(max_length=255)
    descripcion = models.TextField()
    
    # Dates
    fecha_inicio = models.DateField()
    fecha_fin_planificada = models.DateField()
    fecha_fin_real = models.DateField(blank=True, null=True)
    
    # Management
    responsable = models.ForeignKey(User, on_delete=models.SET_NULL)
    estado = models.CharField(max_length=20, choices=ESTADOS)
    
    # Budget
    presupuesto = models.DecimalField(max_digits=12, decimal_places=2)
    
    # Progress
    porcentaje_avance = models.DecimalField(max_digits=5, decimal_places=2, default=0)

Actividad (Activity)

proyectos/models.py
class Actividad(models.Model):
    PRIORIDADES = [
        ('BAJA', 'Baja'),
        ('MEDIA', 'Media'),
        ('ALTA', 'Alta'),
        ('CRITICA', 'Crítica'),
    ]
    
    proyecto = models.ForeignKey('Proyecto', on_delete=models.CASCADE)
    codigo = models.CharField(max_length=50)
    nombre = models.CharField(max_length=255)
    descripcion = models.TextField()
    
    # Schedule
    fecha_inicio = models.DateField()
    fecha_fin = models.DateField()
    duracion_dias = models.IntegerField()
    
    # Dependencies
    predecesoras = models.ManyToManyField('self', 
                                         symmetrical=False,
                                         related_name='sucesoras',
                                         blank=True)
    
    # Assignment
    responsable = models.ForeignKey(User, on_delete=models.SET_NULL)
    ubicacion = models.ForeignKey('activos.Ubicacion', on_delete=models.SET_NULL)
    
    # Status
    estado = models.CharField(max_length=20)
    porcentaje_completado = models.IntegerField(default=0)
    prioridad = models.CharField(max_length=10, choices=PRIORIDADES)
    
    # Location on floor plan
    coordenada_x = models.FloatField(blank=True, null=True)
    coordenada_y = models.FloatField(blank=True, null=True)

DocumentoProyecto (Project Documents)

proyectos/models.py
class DocumentoProyecto(models.Model):
    proyecto = models.ForeignKey('Proyecto', on_delete=models.CASCADE)
    documento = models.ForeignKey('documentos.Documento', on_delete=models.CASCADE)
    fecha_vinculacion = models.DateField(auto_now_add=True)

Project Workflow

1

Create Project

Define project scope, timeline, and budget
proyecto = Proyecto.objects.create(
    nombre="Cooling Tower Replacement",
    fecha_inicio=date(2025, 1, 1),
    fecha_fin_planificada=date(2025, 6, 30),
    presupuesto=Decimal('500000.00'),
    responsable=project_manager
)
2

Define Activities

Break down project into activities with dependencies
# Activity 1: Site preparation
prep = Actividad.objects.create(
    proyecto=proyecto,
    nombre="Site Preparation",
    fecha_inicio=date(2025, 1, 1),
    duracion_dias=10
)

# Activity 2: Equipment delivery (depends on prep)
delivery = Actividad.objects.create(
    proyecto=proyecto,
    nombre="Equipment Delivery",
    fecha_inicio=date(2025, 1, 11),
    duracion_dias=5
)
delivery.predecesoras.add(prep)

# Activity 3: Installation (depends on delivery)
install = Actividad.objects.create(
    proyecto=proyecto,
    nombre="Installation",
    fecha_inicio=date(2025, 1, 16),
    duracion_dias=20
)
install.predecesoras.add(delivery)
3

Track Progress

Update activity completion percentages
actividad.porcentaje_completado = 75
actividad.save()

# Recalculate project progress
proyecto.calcular_avance()
4

Generate Reports

Export Gantt chart and progress reports

Gantt Chart Visualization

Timeline View

Visual representation of project schedule:
proyectos/views.py
def gantt_view(request, proyecto_id):
    proyecto = Proyecto.objects.get(id=proyecto_id)
    actividades = proyecto.actividad_set.all()
    
    # Prepare data for Gantt chart
    gantt_data = []
    for actividad in actividades:
        gantt_data.append({
            'id': actividad.id,
            'text': actividad.nombre,
            'start_date': actividad.fecha_inicio.isoformat(),
            'duration': actividad.duracion_dias,
            'progress': actividad.porcentaje_completado / 100,
            'parent': actividad.proyecto.id,
            'dependencies': [p.id for p in actividad.predecesoras.all()]
        })
    
    return render(request, 'gantt.html', {
        'proyecto': proyecto,
        'gantt_data': json.dumps(gantt_data)
    })

Critical Path Analysis

Identify critical activities:
proyectos/services.py
def calcular_ruta_critica(proyecto):
    """Calculate critical path using forward/backward pass"""
    actividades = list(proyecto.actividad_set.all())
    
    # Forward pass: Calculate earliest start/finish
    for actividad in actividades:
        if not actividad.predecesoras.exists():
            actividad.early_start = proyecto.fecha_inicio
        else:
            max_finish = max([p.early_finish for p in actividad.predecesoras.all()])
            actividad.early_start = max_finish
        
        actividad.early_finish = actividad.early_start + timedelta(days=actividad.duracion_dias)
    
    # Backward pass: Calculate latest start/finish
    for actividad in reversed(actividades):
        if not actividad.sucesoras.exists():
            actividad.late_finish = proyecto.fecha_fin_planificada
        else:
            min_start = min([s.late_start for s in actividad.sucesoras.all()])
            actividad.late_finish = min_start
        
        actividad.late_start = actividad.late_finish - timedelta(days=actividad.duracion_dias)
    
    # Identify critical activities (slack = 0)
    critical_activities = [
        a for a in actividades 
        if (a.late_start - a.early_start).days == 0
    ]
    
    return critical_activities

AI Assistant Integration

Gemini-Powered Q&A

Ask questions about project status:
proyectos/views.py
def ai_chat(request, proyecto_id):
    proyecto = Proyecto.objects.get(id=proyecto_id)
    question = request.POST.get('question')
    
    # Build context from project data
    context = f"""
    Project: {proyecto.nombre}
    Status: {proyecto.estado}
    Progress: {proyecto.porcentaje_avance}%
    Activities: {proyecto.actividad_set.count()}
    Budget: ${proyecto.presupuesto}
    """
    
    # Query Gemini API
    import google.generativeai as genai
    genai.configure(api_key=settings.GEMINI_API_KEY)
    
    model = genai.GenerativeModel('gemini-pro')
    response = model.generate_content(
        f"Context: {context}\n\nQuestion: {question}"
    )
    
    return JsonResponse({'answer': response.text})

Document Linking

Associate technical documents with projects:
proyectos/views.py
def vincular_documento(request, proyecto_id):
    proyecto = Proyecto.objects.get(id=proyecto_id)
    documento_id = request.POST.get('documento_id')
    
    DocumentoProyecto.objects.create(
        proyecto=proyecto,
        documento_id=documento_id
    )
    
    return JsonResponse({'status': 'ok'})

API Endpoints

Activity Management

CRUD operations for projects and activities

Progress Updates

Update activity completion and recalculate project progress

Best Practices

Activity Granularity: Break down activities to 1-2 week durations for better tracking
Circular Dependencies: The system prevents circular predecessor relationships
Regular Updates: Update activity progress weekly for accurate reporting

Documents

Link project documentation

Budgets

Track project costs

Assets

Associate with locations

Build docs developers (and LLMs) love