Skip to main content

Overview

PTEs (Propuestas Técnico-Económicas) are technical-economic proposals that represent the planning phase of projects. This guide covers the complete PTE lifecycle.

Understanding PTEs

What is a PTE?

A PTE is a comprehensive proposal document that includes:
  • Project description and scope
  • Technical requirements
  • Timeline and milestones
  • Resource allocation
  • Cost estimates
  • Client information

PTE Workflow Stages

1

Creation

Initial proposal is created with basic information
2

Planning

Steps are defined and assigned
3

In Process

Work progresses through defined steps
4

Completion

All steps are finished and deliverables submitted
5

Work Order Creation

Approved PTEs can generate work orders (OTEs)

Creating a New PTE

Step-by-Step Guide

1

Navigate to PTE Module

Go to Operaciones > PTEs > Nuevo
2

Fill Basic Information

Enter required fields:

Oficio PTE

Official document number (e.g., PTE-2026-001)

Oficio Solicitud

Request document number

Cliente

Select client organization

Tipo

PTE type/category
3

Set Deadlines

Configure timeline:
  • Fecha Solicitud: Request date
  • Plazo Días: Duration in days
  • Prioridad: Priority level (1-5)
4

Assign Responsibility

Select Responsable del Proyecto from the dropdown
5

Submit

Click Guardar to create the PTE

Backend Implementation

operaciones/views/pte.py
@require_http_methods(["POST"])
@login_required
@registrar_actividad
def crear_pte(request):
    # Extract form data
    oficio_pte = request.POST.get('oficio_pte', 'SIN FOLIO')
    descripcion_trabajo = request.POST.get('descripcion_trabajo','POR DEFINIR')
    id_cliente = request.POST.get('id_cliente')
    responsable_proyecto = request.POST.get('responsable_proyecto')
    plazo_dias = int(request.POST.get('plazo_dias', 0))
    
    # Validate required fields
    if not id_cliente:
        return JsonResponse({
            'exito': False,
            'detalles': 'El cliente es obligatorio'
        })
    
    # Create PTE header
    pte_header = PTEHeader.objects.create(
        oficio_pte=oficio_pte,
        descripcion_trabajo=descripcion_trabajo,
        id_responsable_proyecto_id=responsable_proyecto,
        plazo_dias=plazo_dias,
        id_cliente_id=id_cliente,
        estatus=1  # PENDIENTE
    )
    
    # Auto-create steps based on client type
    clientes = Cliente.objects.get(id=id_cliente)
    tipo_cliente = clientes.id_tipo_id
    pasos = Paso.objects.filter(activo=1, id_tipo_cliente_id=tipo_cliente)
    
    for paso in pasos:
        PTEDetalle.objects.create(
            id_pte_header_id=pte_header.id,
            id_paso_id=paso.id,
            estatus_paso_id=1,  # PENDIENTE
            comentario=''
        )
Steps are automatically created based on the client type when a PTE is created.

PTE Status Management

Status Types

StatusCodeDescriptionColor
PENDIENTE1Awaiting startYellow
PROCESO2Work in progressBlue
ENTREGADA3Completed and deliveredGreen
CANCELADA4CancelledRed
SUSPENDIDA9Temporarily suspendedGray

Changing PTE Status

1

Open PTE Details

Click on a PTE in the list to view details
2

Click Status Button

Click the “Cambiar Estatus” button
3

Select New Status

Choose the new status from the dropdown
4

Add Comments (Optional)

Provide explanation for status change
5

Set Delivery Date

For ENTREGADA status, set the delivery date
6

Save Changes

Click Guardar to apply the status change
operaciones/views/pte.py
@require_http_methods(["POST"])
@login_required
@registrar_actividad
def cambiar_estatus_pte(request):
    pte_id = request.POST.get('pte_id')
    nuevo_estatus = request.POST.get('nuevo_estatus')
    fecha_entrega = request.POST.get('fecha_entrega', None)
    
    pte = PTEHeader.objects.get(id=pte_id)
    pte.estatus = nuevo_estatus
    
    # Set delivery date when marking as completed
    if int(nuevo_estatus) == 3:
        if fecha_entrega:
            pte.fecha_entrega = fecha_entrega
        else:
            pte.fecha_entrega = timezone.now()
    
    pte.save()

Managing PTE Steps

Viewing Steps

Each PTE has multiple steps that must be completed:

PTE Steps DataTable

The steps table shows:
  • Step order and description
  • Current status
  • Start and end dates
  • Responsible person
  • Progress percentage
  • File attachments

Updating Step Status

1

Access Step Actions

Click the action button next to a step
2

Change Status

Select from:
  • PENDIENTE: Not started
  • PROCESO: In progress
  • COMPLETADO: Finished
  • NO APLICA: Not applicable
3

Set Dates

Update:
  • Fecha Inicio
  • Fecha Término
  • Fecha Entrega
4

Add Notes

Enter comments about progress or issues
5

Upload Files

Attach deliverables or evidence
operaciones/views/pte.py
@require_http_methods(["POST"])
@login_required
@registrar_actividad
def cambiar_estatus_paso(request):
    paso_id = request.POST.get('paso_id')
    nuevo_estatus = request.POST.get('nuevo_estatus')
    comentario = request.POST.get('comentario','')
    
    detalle = PTEDetalle.objects.get(id=paso_id)
    detalle.estatus_paso_id = int(nuevo_estatus)
    detalle.comentario = comentario
    
    # Auto-set completion date
    if int(nuevo_estatus) == 3:
        detalle.fecha_entrega = timezone.now()
    
    detalle.save()
    
    # Check if all steps completed
    verificar_y_actualizar_paso_4(detalle.id_pte_header_id)

Progress Calculation

PTE Progress Formula

detalles = PTEDetalle.objects.filter(id_pte_header_id=pte.id)
total_pasos = detalles.count()
pasos_completados = detalles.filter(estatus_paso__in=[3,14]).count()

progreso = (pasos_completados / total_pasos) * 100
Note: Status 3 = COMPLETADO, Status 14 = NO APLICA

Special Step: Volumetría (Step 4)

Step 4 often contains substeps that must all be completed:
Click on Step 4 to expand substeps (tipo=2)
Mark each substep as completed individually
When all substeps are done, Step 4 is automatically marked complete:
operaciones/views/pte.py
def verificar_y_actualizar_paso_4(pte_header_id):
    subpasos = PTEDetalle.objects.filter(
        id_pte_header_id=pte_header_id,
        id_paso__tipo=2
    )
    
    total_subpasos = subpasos.count()
    subpasos_completados = subpasos.filter(estatus_paso__in=[3, 14]).count()
    
    if subpasos_completados == total_subpasos:
        paso_4.estatus_paso_id = 3
        paso_4.comentario = "Entregables finalizados"
        paso_4.save()

Editing PTEs

Only users with operaciones.change_pteheader permission can edit PTEs.
1

Open Edit Form

Click Editar button on PTE details page
2

Modify Fields

Update any editable fields (status cannot be changed here)
3

Save Changes

Click Guardar to apply changes
operaciones/views/pte.py
@require_http_methods(["POST"])
@login_required
@registrar_actividad
def editar_pte(request):
    pte_id = request.POST.get('id')
    pte = get_object_or_404(PTEHeader, id=pte_id)
    
    pte.oficio_pte = request.POST.get('oficio_pte', pte.oficio_pte)
    pte.descripcion_trabajo = request.POST.get('descripcion_trabajo')
    pte.plazo_dias = float(request.POST.get('plazo_dias'))
    
    pte.save()

Searching and Filtering PTEs

Use the search box to find PTEs by:
  • Oficio PTE
  • Description
  • Responsible person

Advanced Filters

By Status

Filter by PENDIENTE, PROCESO, ENTREGADA, etc.

By Type

Filter by PTE type/category

By Year

Filter PTEs by year (extracted from oficio_pte)

By Client

Filter by client organization

By Responsible

Filter by project manager

Creating Work Orders from PTEs

Once a PTE reaches 100% completion:
1

Verify 100% Complete

Ensure all steps are marked COMPLETADO or NO APLICA
2

Click 'Create OT'

Button appears when PTE is 100% complete
3

Enter OT Information

Provide:
  • Oficio OT (work order number)
  • Tipo OT (work order type)
  • Additional details
4

Submit

System creates work order and links it to PTE
operaciones/views/pte.py
@registrar_actividad
def crear_ot_desde_pte(request):
    pte_id = request.POST.get('pte_id')
    oficio_ot = request.POST.get('oficio')
    
    pte = PTEHeader.objects.get(id=pte_id)
    
    # Verify 100% complete
    detalles = PTEDetalle.objects.filter(id_pte_header_id=pte.id)
    pasos_completados = detalles.filter(estatus_paso_id__in=[3, 4, 14]).count()
    progreso = (pasos_completados / detalles.count()) * 100
    
    if progreso < 100:
        return JsonResponse({
            'exito': False,
            'detalles': 'PTE must be 100% complete'
        })
    
    # Create work order
    ote = OTE.objects.create(
        id_pte_header=pte,
        orden_trabajo=oficio_ot,
        descripcion_trabajo=pte.descripcion_trabajo,
        # Copy relevant fields from PTE
    )
Some PTE steps (like volumetry) are automatically copied to the new work order.

Deleting PTEs

Deletion requires operaciones.delete_pteheader permission and is logical (not physical).
operaciones/views/pte.py
@require_http_methods(["POST"])
@login_required
@registrar_actividad
def eliminar_pte(request):
    if not request.user.has_perm('operaciones.delete_pteheader'):
        return JsonResponse({
            'detalles': 'No tienes permiso para eliminar PTEs',
            'exito': False
        })
    
    pte_id = request.POST.get('id')
    pte = PTEHeader.objects.get(id=pte_id)
    pte.estatus = 0  # Logical deletion
    pte.save()

Best Practices

Clear Descriptions

Write detailed work descriptions for better tracking

Realistic Deadlines

Set achievable timelines based on actual capacity

Regular Updates

Update step status frequently to reflect progress

Document Everything

Attach all deliverables and evidence to steps

Use Comments

Add notes explaining decisions or issues

Review Before Complete

Verify all information before marking as ENTREGADA

Executing Work Orders

Learn how to manage work orders created from PTEs

Activity Logs

View PTE modification history

Build docs developers (and LLMs) love