Arquitectura#
Arquitectura técnica y patrones de diseño utilizados en Construbot.
Descripción general#
Construbot es un sistema de gestión de construcción basado en Django creado con patrones modernos y mejores prácticas. Esta sección explica las decisiones arquitectónicas, los modelos de datos y el diseño del sistema.
Referencia rápida#
Pila de tecnología#
Servidor:
Django 3.2.19 (LTS)
Pitón 3.9.17+
PostgreSQL 12+
Redis 6+
Cola de tareas:
Apio 5.2.7
corredor de Redis
API:
Marco REST de Django 3.13.1
SimpleJWT 5.2.0
Bibliotecas clave:
django-treebeard 4.5.1 (modelos jerárquicos)
django-allauth 0.51.0 (autenticación)
django-autocomplete-light 3.9.4 (widgets de autocompletar)
reportlab 3.6.12 (generación de PDF)
openpyxl 3.0.10 (importación/exportación de Excel)
Componentes del sistema#
Capa de aplicación#
┌──────────────────────────────────────────┐
│ Web Clients / API Clients │
└────────────────┬─────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Nginx (Reverse Proxy / SSL) │
└────────────────┬─────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Gunicorn (WSGI Server) │
│ ┌──────────────────────────────┐ │
│ │ Django Application │ │
│ │ ├─ proyectos (core logic) │ │
│ │ ├─ users (auth & accounts) │ │
│ │ ├─ api (REST endpoints) │ │
│ │ └─ core (utilities) │ │
│ └──────────────────────────────┘ │
└────────────────┬─────────────────────────┘
│
┌─────────┴──────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ PostgreSQL │ │ Redis │
│ (Database) │ │(Cache/Queue) │
└──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│Celery Workers│
│(Background) │
└──────────────┘
Flujo de datos#
Solicitud de usuario:
El usuario accede a la aplicación → Nginx
Nginx representa a Gunicorn
Gunicorn ejecuta el ciclo de solicitud/respuesta de Django
Django consulta PostgreSQL para obtener datos
Django usa Redis para el almacenamiento en caché
Respuesta emitida y devuelta
Tarea en segundo plano:
La acción del usuario desencadena la tarea → Retraso de apio()
Tarea en cola en Redis
El trabajador del apio retoma su tarea
El trabajador ejecuta la tarea (por ejemplo, enviar correo electrónico, generar PDF)
Resultado almacenado en Redis (opcional)
Estructura de la aplicación#
Aplicaciones Django#
construbot.users - Gestión de usuarios
Modelo de usuario personalizado (autenticación basada en correo electrónico)
Modelos de empresa y cliente
Niveles de permisos (NivelAcceso)
Motores de autenticación
construbot.proyectos - Lógica empresarial central
Gestión de contratos (Contrato)
Gestión de contraparte (Contraparte)
Seguimiento de estimación (Estimación)
Estructuras de datos jerárquicas
Cálculos financieros
construbot.api - API REST
autenticación JWT
Puntos finales API para acceso móvil/externo
Serializadores y conjuntos de vistas
Puntos finales de migración de datos
construbot.core - Utilidades compartidas
Modelos base y mixins.
Backend de autenticación personalizada
Funciones de utilidad
Plantillas compartidas
construbot.account_config - Configuración de cuenta
Configuraciones específicas de la empresa
Formularios de inicio de sesión personalizados
Preferencias de cuenta
construbot.taskapp - Configuración de apio
Inicialización de la aplicación de apio
Definiciones de tareas
Configuración de tareas periódicas
Estructura del directorio#
construbot/
├── construbot/ # Main Django project
│ ├── config/ # Project configuration
│ │ ├── settings/ # Environment-specific settings
│ │ │ ├── base.py # Shared settings
│ │ │ ├── local.py # Development
│ │ │ ├── test.py # Testing
│ │ │ └── production.py # Production
│ │ ├── urls.py # Root URL configuration
│ │ └── wsgi.py # WSGI application
│ │
│ ├── users/ # User management app
│ │ ├── models.py # User, Company, Customer
│ │ ├── views.py # User views
│ │ ├── forms.py # User forms
│ │ └── admin.py # Admin interface
│ │
│ ├── proyectos/ # Core business app
│ │ ├── models.py # Business models
│ │ ├── views.py # Business views
│ │ ├── forms.py # Business forms
│ │ └── migrations/ # Database migrations
│ │
│ ├── api/ # REST API app
│ │ ├── views.py # API viewsets
│ │ ├── serializers.py # Data serializers
│ │ └── urls.py # API routes
│ │
│ ├── core/ # Shared utilities
│ │ ├── models.py # Base models
│ │ ├── backends.py # Auth backend
│ │ └── utils.py # Utility functions
│ │
│ ├── static/ # Static files
│ │ ├── css/ # Stylesheets
│ │ ├── js/ # JavaScript
│ │ └── images/ # Images
│ │
│ ├── templates/ # Django templates
│ │ ├── base.html # Base template
│ │ └── ... # App templates
│ │
│ └── media/ # User uploads
│
├── requirements/ # Dependencies
│ ├── base.txt # Core dependencies
│ ├── local.txt # Development
│ ├── test.txt # Testing
│ └── production.txt # Production
│
├── tests/ # Test suite
│ └── ... # Test files
│
├── docs/ # Documentation
│ └── ... # Documentation files
│
├── compose/ # Docker configuration
│ ├── local/ # Local development
│ └── production/ # Production
│
├── manage.py # Django management script
├── setup.py # Package setup
├── docker-compose.yml # Docker Compose config
└── Makefile # Development commands
Patrones de diseño#
Multi-inquilino#
Jerarquía de tres niveles:
Customer (Top-level account)
└── Company (Business entity)
└── User (Individual with permissions)
Aislamiento de datos:
Todos los datos comerciales enfocados a la empresa
Los usuarios pueden pertenecer a varias empresas.
Empresa activa rastreada en la sesión
Consulte Multi-inquilino para obtener más detalles.
Modelos Jerárquicos#
Camino materializado de Django-treebeard:
Los contratos (Contrato) forman estructuras de árbol:
Main Contract
├── Subcontract 1
│ ├── Sub-subcontract 1.1
│ └── Sub-subcontract 1.2
└── Subcontract 2
Beneficios:
Consultas eficientes entre padres e hijos
Agregaciones de árboles (cantidades totales)
Operaciones de movimiento
Consultas basadas en rutas
Implementación:
from treebeard.mp_tree import MP_Node
class Contrato(MP_Node):
# Inherits: path, depth, numchild
# Methods: get_children(), get_ancestors(), etc.
Autenticación personalizada#
Autenticación basada en correo electrónico:
Sin campo de nombre de usuario
Correo electrónico como identificador único
Backend de autenticación personalizada
Soporte multiempresa:
El usuario puede acceder a múltiples empresas.
Cambio de empresa sin volver a iniciar sesión
Permisos por empresa
Consulte autenticación para obtener más detalles.
Sistema de permisos#
Seis niveles de permisos (NIVELES_ACCESO):
Auxiliar (1) - Ver solo
Coordinador (2) - Crear/editar
Director (3) - CRUD completo
Corporativo (4) - Multiempresa
Soporte (5) - Acceso al soporte
Superusuario (6) - Acceso completo al sistema
Consulte Niveles de permiso para obtener más detalles.
Patrones de acceso a datos#
Optimización de consultas#
Seleccione Relacionado (claves externas):
# Avoid N+1 queries
contratos = Contrato.objects.select_related('contraparte', 'company')
Relacionado con la captación previa (muchos a muchos):
# Optimize related objects
users = User.objects.prefetch_related('companies', 'user_companies')
Índices de bases de datos:
class Contrato(models.Model):
folio = models.CharField(max_length=100, db_index=True)
class Meta:
indexes = [
models.Index(fields=['company', 'fecha_inicio']),
]
Estrategia de almacenamiento en caché#
Almacenamiento en caché por vista:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 15 minutes
def dashboard_view(request):
...
Almacenamiento en caché de fragmentos de plantilla:
{% load cache %}
{% cache 600 sidebar request.user.id %}
... expensive template code ...
{% endcache %}
Almacenamiento en caché de resultados de consultas:
from django.core.cache import cache
def get_company_stats(company_id):
key = f'company_stats_{company_id}'
stats = cache.get(key)
if stats is None:
stats = calculate_stats(company_id)
cache.set(key, stats, 3600) # 1 hour
return stats
Transacciones atómicas#
Habilitado de forma predeterminada:
# In settings/base.py
DATABASES = {
'default': {
...
'ATOMIC_REQUESTS': True,
}
}
Control manual de transacciones:
from django.db import transaction
@transaction.atomic
def create_contract_with_concepts(contract_data, concepts_data):
contract = Contrato.objects.create(**contract_data)
for concept_data in concepts_data:
Concept.objects.create(contract=contract, **concept_data)
return contract
Diseño API#
Estructura de la API REST#
URL base: /api/v1/
Autenticación: tokens JWT
Puntos finales:
POST /api/v1/api-token-auth/ # Obtain token
POST /api/v1/api-token-refresh/ # Refresh token
GET /api/v1/contracts/ # List contracts
POST /api/v1/contracts/ # Create contract
GET /api/v1/contracts/:id/ # Retrieve contract
PUT /api/v1/contracts/:id/ # Update contract
DELETE /api/v1/contracts/:id/ # Delete contract
Formato de respuesta:
{
"count": 100,
"next": "http://api.example.com/api/v1/contracts/?page=2",
"previous": null,
"results": [...]
}
Consulte API para obtener la documentación API completa.
Arquitectura de seguridad#
Flujo de autenticación#
Aplicación web:
El usuario envía correo electrónico/contraseña
El backend se autentica contra el modelo de usuario
Sesión creada con el contexto de la empresa.
Usuario redirigido al panel
API:
El cliente publica credenciales en
/api-token-auth/El servidor valida y devuelve el token JWT
El cliente incluye el token en el encabezado
Autorización: Portador <token>El servidor valida el token en cada solicitud
Consideraciones de rendimiento#
Base de datos#
Almacenamiento en caché#
Redis para backend de caché
Almacenamiento de sesiones en caché
Almacenamiento en caché de resultados de consultas
Almacenamiento en caché de fragmentos de plantilla
Archivos estáticos#
WhiteNoise para un servicio eficiente
Compresión Gzip/Brotli
Encabezados de caché de futuro lejano
CDN para implementaciones de alto tráfico
Tareas en segundo plano#
Apio para operaciones asincrónicas
Envío de correo electrónico en segundo plano
Generación de PDF en segundo plano
Tareas programadas con Celery Beat
Escalabilidad#
Escalado vertical#
Aumentar la CPU/RAM del servidor
Actualizar instancia de base de datos
Agregar memoria Redis
Escala horizontal#
Múltiples servidores de aplicaciones Django
Equilibrador de carga (ALB/Nginx)
Base de datos administrada (RDS con réplicas de lectura)
Caché externo (ElastiCache)
S3 para archivos multimedia
Los servidores de aplicaciones sin estado permiten un fácil escalado horizontal.
Puntos de Monitoreo#
Métricas de aplicación#
Tiempos de solicitud/respuesta
Tasas de error (4xx, 5xx)
Rendimiento de consultas de bases de datos
Proporción de aciertos/errores de caché
Longitud de la cola de tareas de apio
Métricas de infraestructura#
uso de CPU
Uso de memoria
E/S de disco
Tráfico de red
Conexiones de bases de datos
Métricas comerciales#
Usuarios activos
Contratos creados
Estimaciones generadas
Descargas de PDF
Uso de API
Consulte Despliegue para conocer la configuración del monitoreo.
Flujo de trabajo de desarrollo#
Desarrollo Local#
Utilice Docker Compose para un entorno coherente
Ejecute
make devpara iniciar los serviciosRecarga automática de cambios de código (servidor de desarrollo Django)
Utilice
make shellpara Django shellEjecute
make testantes de confirmar
Consulte Instalación para la configuración.
Estrategia de prueba#
Pruebas unitarias para modelos y utilidades.
Pruebas de integración para vistas.
Pruebas API para puntos finales REST
Objetivo de cobertura: >80%
Consulte Pruebas para obtener una guía de prueba.
Proceso de implementación#
Ejecutar pruebas (
hacer prueba)Construir imágenes de Docker
Ejecutar migraciones de bases de datos
Recopilar archivos estáticos
Reiniciar los servidores de aplicaciones
Verificar implementación
Consulte Despliegue para obtener una guía de implementación.
Ver también#
Estructura de configuración - Settings organization
Multi-inquilino - Multi-tenant architecture
Esquema de base de datos - Database design
Estructura de URL - URL routing
API - API documentation