All checks were successful
DEPLOY_MULTI_BRACH/pipeline/head This commit looks good
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
4.2 KiB
Markdown
111 lines
4.2 KiB
Markdown
# Convenciones del Ecosistema V-Encore Lab
|
|
|
|
## Ecosistema de microservicios
|
|
|
|
| Repo | Rol | Puerto |
|
|
|------|-----|--------|
|
|
| `django-core-base` | Hub orquestador principal | 8000 |
|
|
| `api_backoffice` | Consulta y gestión de BD | 8001 |
|
|
| `api_comunicaciones` | Emails, notificaciones, webhooks | 8002 |
|
|
| `api_documentacion` | Generación y gestión de documentos | 8003 |
|
|
| `web_interno` | Panel de gestión (React + Ant Design) | 3000 |
|
|
|
|
## Stack Django
|
|
|
|
- Django 5.0 + DRF + SimpleJWT
|
|
- Apps bajo `app/`. Prefijo `/api/` en todas las URLs salvo `admin/`.
|
|
- Patrón 3 capas: **URL → View → Action**
|
|
- SQL con `connection.cursor()` y placeholders (`%s`). Nunca concatenar strings.
|
|
|
|
## Patrón de vistas — 4 bloques obligatorios
|
|
|
|
```python
|
|
from general.utilidades.acciones import LogService
|
|
|
|
class MiVista(APIView):
|
|
authentication_classes = [JWTAuthentication]
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
path = '/mi-app/mi-endpoint/'
|
|
|
|
# Bloque 1 — Inicio Log
|
|
log_id = LogService.gestionar_log(self, request, path=path)
|
|
|
|
try:
|
|
# Bloque 2 — Data Cleaning
|
|
data = request.data
|
|
LogService.gestionar_log(self, request, log_id=log_id,
|
|
path=path, body_request=data, status_code=100)
|
|
params = {'campo': data.get('campo')}
|
|
except Exception as error:
|
|
response = {'error': str(error)}
|
|
LogService.gestionar_log(self, request, log_id=log_id,
|
|
path=path, body_response=response, status_code=400)
|
|
return JsonResponse(response, status=400)
|
|
|
|
try:
|
|
# Bloque 3 — Action Call
|
|
resultado = mi_accion(params)
|
|
# Bloque 4 — Cierre Log
|
|
LogService.gestionar_log(self, request, log_id=log_id,
|
|
path=path, body_response=resultado, status_code=200)
|
|
return JsonResponse(resultado, status=200)
|
|
except Exception as error:
|
|
response = {'error': str(error)}
|
|
LogService.gestionar_log(self, request, log_id=log_id,
|
|
path=path, body_response=response, status_code=500)
|
|
return JsonResponse(response, status=500)
|
|
```
|
|
|
|
## LogService — reglas
|
|
|
|
- Siempre llamar como `LogService.gestionar_log(self, request, ...)` — pasar `self` de la vista.
|
|
- Primera llamada (sin `log_id`): crea el registro, devuelve el `log_id`.
|
|
- Llamadas siguientes: actualizar con `log_id=log_id`.
|
|
- `body_request` y `body_response` se serializan con `DjangoJSONEncoder` — soporta `datetime.date`, `Decimal`, etc.
|
|
- `status_code` como entero. Usar `is not None` para comprobar (0 es válido).
|
|
|
|
## Base de datos
|
|
|
|
- `DB_HOST` definido → PostgreSQL
|
|
- `DB_HOST` no definido → SQLite en `app/data/db.sqlite3`
|
|
- Migraciones siempre desde `app/`: `cd app && python manage.py migrate`
|
|
- SQL INSERT con psycopg2: usar `INSERT ... RETURNING id` + `cursor.fetchone()`. **Nunca `cursor.lastrowid`**.
|
|
- Booleans en psycopg2: pasar `True`/`False`, no `1`/`0`.
|
|
|
|
## Flujo de ramas
|
|
|
|
```
|
|
pre-dev → dev → master
|
|
```
|
|
|
|
- `pre-dev`: desarrollo activo — aquí entran todos los cambios
|
|
- `dev`: validación previa a producción
|
|
- `master`: producción estable
|
|
- Merges siempre con `--no-ff`
|
|
- **NUNCA** propagar en sentido inverso (master → dev o dev → pre-dev)
|
|
- Secuencia correcta:
|
|
```bash
|
|
git checkout pre-dev && git merge <mi-cambio> --no-ff
|
|
git checkout dev && git merge pre-dev --no-ff && git push origin dev
|
|
git checkout master && git merge dev --no-ff && git push origin master
|
|
```
|
|
|
|
## Estructura de app Django
|
|
|
|
```
|
|
app/
|
|
├── api_config/ # settings.py, urls.py, wsgi.py
|
|
├── general/ # LogService, utils — NO tiene modelos propios
|
|
├── backend_admin/ # Modelo Log (audit_logs), admin panel
|
|
├── common/ # Modelos y utilidades compartidas entre apps
|
|
├── <feature_app>/ # Una app por dominio de negocio
|
|
├── data/ # SQLite (gitignored, solo .gitkeep versionado)
|
|
└── manage.py
|
|
```
|
|
|
|
## Fixtures
|
|
|
|
- `loaddata` ignora `auto_now_add=True` — incluir fechas explícitas en el JSON o falla con NOT NULL en PostgreSQL.
|