Architecture#
Technical architecture and design patterns used in Construbot.
Overview#
Construbot is a Django-based construction management system built with modern patterns and best practices. This section explains the architectural decisions, data models, and system design.
Quick Reference#
Technology Stack#
Backend:
Django 3.2.19 (LTS)
Python 3.9.17+
PostgreSQL 12+
Redis 6+
Task Queue:
Celery 5.2.7
Redis broker
API:
Django REST Framework 3.13.1
SimpleJWT 5.2.0
Key Libraries:
django-treebeard 4.5.1 (hierarchical models)
django-allauth 0.51.0 (authentication)
django-autocomplete-light 3.9.4 (autocomplete widgets)
reportlab 3.6.12 (PDF generation)
openpyxl 3.0.10 (Excel import/export)
System Components#
Application Layer#
┌──────────────────────────────────────────┐
│ 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) │
└──────────────┘
Data Flow#
User Request:
User accesses application → Nginx
Nginx proxies to Gunicorn
Gunicorn runs Django request/response cycle
Django queries PostgreSQL for data
Django uses Redis for caching
Response rendered and returned
Background Task:
User action triggers task → Celery delay()
Task queued in Redis
Celery worker picks up task
Worker executes task (e.g., send email, generate PDF)
Result stored in Redis (optional)
Application Structure#
Django Apps#
construbot.users - User management
Custom User model (email-based auth)
Company and Customer models
Permission levels (NivelAcceso)
Authentication backends
construbot.proyectos - Core business logic
Contract management (Contrato)
Counterparty management (Contraparte)
Estimate tracking (Estimate)
Hierarchical data structures
Financial calculations
construbot.api - REST API
JWT authentication
API endpoints for mobile/external access
Serializers and viewsets
Data migration endpoints
construbot.core - Shared utilities
Base models and mixins
Custom authentication backend
Utility functions
Shared templates
construbot.account_config - Account configuration
Company-specific settings
Custom login forms
Account preferences
construbot.taskapp - Celery configuration
Celery app initialization
Task definitions
Periodic task setup
Directory Structure#
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
Design Patterns#
Multi-Tenancy#
Three-level hierarchy:
Customer (Top-level account)
└── Company (Business entity)
└── User (Individual with permissions)
Data isolation:
All business data scoped to Company
Users can belong to multiple Companies
Active company tracked in session
See Multi-Tenancy for details.
Hierarchical Models#
django-treebeard Materialized Path:
Contracts (Contrato) form tree structures:
Main Contract
├── Subcontract 1
│ ├── Sub-subcontract 1.1
│ └── Sub-subcontract 1.2
└── Subcontract 2
Benefits:
Efficient parent/child queries
Tree aggregations (sum amounts)
Move operations
Path-based queries
Implementation:
from treebeard.mp_tree import MP_Node
class Contrato(MP_Node):
# Inherits: path, depth, numchild
# Methods: get_children(), get_ancestors(), etc.
Custom Authentication#
Email-based authentication:
No username field
Email as unique identifier
Custom authentication backend
Multi-company support:
User can access multiple companies
Company switch without re-login
Per-company permissions
See Authentication for details.
Permission System#
Six permission levels (NIVELES_ACCESO):
Auxiliar (1) - View only
Coordinador (2) - Create/edit
Director (3) - Full CRUD
Corporativo (4) - Cross-company
Soporte (5) - Support access
Superusuario (6) - Full system access
See Permission Levels for details.
Data Access Patterns#
Query Optimization#
Select Related (foreign keys):
# Avoid N+1 queries
contratos = Contrato.objects.select_related('contraparte', 'company')
Prefetch Related (many-to-many):
# Optimize related objects
users = User.objects.prefetch_related('companies', 'user_companies')
Database indexes:
class Contrato(models.Model):
folio = models.CharField(max_length=100, db_index=True)
class Meta:
indexes = [
models.Index(fields=['company', 'fecha_inicio']),
]
Caching Strategy#
Per-view caching:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 15 minutes
def dashboard_view(request):
...
Template fragment caching:
{% load cache %}
{% cache 600 sidebar request.user.id %}
... expensive template code ...
{% endcache %}
Query result caching:
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
Atomic Transactions#
Enabled by default:
# In settings/base.py
DATABASES = {
'default': {
...
'ATOMIC_REQUESTS': True,
}
}
Manual transaction control:
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
API Design#
REST API Structure#
Base URL: /api/v1/
Authentication: JWT tokens
Endpoints:
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
Response format:
{
"count": 100,
"next": "http://api.example.com/api/v1/contracts/?page=2",
"previous": null,
"results": [...]
}
See API for complete API documentation.
Security Architecture#
Authentication Flow#
Web application:
User submits email/password
Backend authenticates against User model
Session created with company context
User redirected to dashboard
API:
Client posts credentials to
/api-token-auth/Server validates and returns JWT token
Client includes token in
Authorization: Bearer <token>headerServer validates token on each request
Performance Considerations#
Database#
Connection pooling (
CONN_MAX_AGE)Query optimization (select_related/prefetch_related)
Database indexes on frequently queried fields
Atomic requests for data integrity
Caching#
Redis for cache backend
Session storage in cache
Query result caching
Template fragment caching
Static Files#
WhiteNoise for efficient serving
Gzip/Brotli compression
Far-future cache headers
CDN for high-traffic deployments
Background Tasks#
Celery for asynchronous operations
Email sending in background
PDF generation in background
Scheduled tasks with Celery Beat
Scalability#
Vertical Scaling#
Increase server CPU/RAM
Upgrade database instance
Add Redis memory
Horizontal Scaling#
Multiple Django application servers
Load balancer (ALB/Nginx)
Managed database (RDS with read replicas)
External cache (ElastiCache)
S3 for media files
Stateless application servers enable easy horizontal scaling.
Monitoring Points#
Application Metrics#
Request/response times
Error rates (4xx, 5xx)
Database query performance
Cache hit/miss ratio
Celery task queue length
Infrastructure Metrics#
CPU usage
Memory usage
Disk I/O
Network traffic
Database connections
Business Metrics#
Active users
Contracts created
Estimates generated
PDF downloads
API usage
See Deployment for monitoring setup.
Development Workflow#
Local Development#
Use Docker Compose for consistent environment
Run
make devto start servicesCode changes auto-reload (Django development server)
Use
make shellfor Django shellRun
make testbefore committing
See Installation for setup.
Testing Strategy#
Unit tests for models and utilities
Integration tests for views
API tests for REST endpoints
Coverage target: >80%
See Testing for testing guide.
Deployment Process#
Run tests (
make test)Build Docker images
Run database migrations
Collect static files
Restart application servers
Verify deployment
See Deployment for deployment guide.
See Also#
Settings Structure - Settings organization
Multi-Tenancy - Multi-tenant architecture
Database Schema - Database design
URL Structure - URL routing
API - API documentation