# django-core-base · API Hub Orquestador

> V-Encore Lab — Microservicio principal. Actúa como orquestador y punto de entrada central del ecosistema SaaS.  
> Puerto por defecto: **8000**

---

## Tabla de contenidos

1. [Requisitos previos](#requisitos-previos)
2. [Inicio rápido — Desarrollo local](#inicio-rápido--desarrollo-local)
3. [Variables de entorno](#variables-de-entorno)
4. [Base de datos](#base-de-datos)
5. [Docker — Producción](#docker--producción)
6. [Estructura del proyecto](#estructura-del-proyecto)
7. [Endpoints principales](#endpoints-principales)
8. [Patrón LogService](#patrón-logservice)
9. [Flujo de ramas](#flujo-de-ramas)
10. [Mantenimiento](#mantenimiento)

---

## Requisitos previos

| Herramienta | Versión mínima |
|-------------|---------------|
| Python      | 3.11          |
| pip         | 23+           |
| Docker      | 24+           |
| Docker Compose | v2         |
| Git         | 2.40+         |

---

## Inicio rápido — Desarrollo local

```bash
# 1. Clonar
git clone https://git.v-encore-lab.com/Proyecto-SaaS/django-core-base.git
cd django-core-base

# 2. Entorno virtual
python -m venv .venv
source .venv/bin/activate        # Linux/Mac
.venv\Scripts\activate           # Windows

# 3. Dependencias
pip install -r deployments/requirements.txt

# 4. Variables de entorno
cp .env.example .env
# Editar .env según el entorno (ver sección Variables de entorno)

# 5. Migraciones (SQLite en local)
cd app
python manage.py migrate

# 6. Superusuario (primera vez)
python manage.py createsuperuser

# 7. Servidor de desarrollo
python manage.py runserver 0.0.0.0:8000
```

Accesos:
- API: http://localhost:8000/api/
- Admin: http://localhost:8000/admin/

---

## Variables de entorno

Copia `.env.example` a `.env` y ajusta los valores:

| Variable       | Descripción                                      | Ejemplo / Default          |
|----------------|--------------------------------------------------|----------------------------|
| `SECRET_KEY`   | Clave secreta Django                             | `django-insecure-...`      |
| `DEBUG`        | Modo debug                                       | `True` (dev) / `False` (prod) |
| `ALLOWED_HOSTS`| Hosts permitidos (separados por coma)            | `localhost,127.0.0.1`      |
| `DB_HOST`      | Host PostgreSQL. **Si no se define → SQLite**    | `localhost` / vacío        |
| `DB_PORT`      | Puerto PostgreSQL                                | `5432`                     |
| `DB_NAME`      | Nombre de la base de datos                       | `vencorelab`               |
| `DB_USER`      | Usuario PostgreSQL                               | `postgres`                 |
| `DB_PASSWORD`  | Contraseña PostgreSQL                            | `postgres`                 |

---

## Base de datos

### Desarrollo local — SQLite

Si `DB_HOST` **no** está definido en `.env`, Django usa automáticamente SQLite:

```
app/data/db.sqlite3
```

```bash
cd app
python manage.py migrate          # crea app/data/db.sqlite3
python manage.py createsuperuser
```

La carpeta `app/data/` está en `.gitignore` (solo se versiona `.gitkeep`).

### Producción — PostgreSQL

Define `DB_HOST` en `.env` para activar el driver PostgreSQL:

```env
DB_HOST=localhost
DB_PORT=5432
DB_NAME=vencorelab
DB_USER=postgres
DB_PASSWORD=supersecret
```

```bash
cd app
python manage.py migrate
```

### Comandos útiles de migración

```bash
cd app

# Ver migraciones pendientes
python manage.py showmigrations

# Crear migraciones de una app
python manage.py makemigrations <app_name>

# Aplicar todas las migraciones
python manage.py migrate

# Revertir migraciones de una app al estado inicial
python manage.py migrate <app_name> zero
```

---

## Docker — Producción

```bash
# Construir e iniciar
docker-compose up --build -d

# Ver logs
docker-compose logs -f

# Parar
docker-compose down

# Parar y eliminar volúmenes (¡cuidado en producción!)
docker-compose down -v
```

El contenedor expone el puerto **8000**.

Para producción con PostgreSQL, asegúrate de que `.env` tenga `DB_HOST` apuntando al host correcto (puede ser el nombre del servicio en la red Docker).

---

## Estructura del proyecto

```
django-core-base/
├── app/
│   ├── api_config/          # Configuración Django (settings, urls, wsgi)
│   ├── general/             # App transversal
│   │   └── utilidades/
│   │       ├── acciones.py  # LogService — auditoría centralizada
│   │       └── utils.py     # Utilidades HTTP (get_client_ip, etc.)
│   ├── backend_admin/       # App admin: modelo Log, endpoints de gestión
│   ├── common/              # Modelos y utilidades compartidas
│   ├── promociones/         # App de ejemplo
│   ├── automatizados/       # Endpoints para Jenkins/automatizaciones
│   ├── data/                # Directorio de la BD SQLite (gitignored)
│   │   └── .gitkeep
│   └── manage.py
├── deployments/
│   ├── requirements.txt
│   └── Dockerfile
├── docker-compose.yml
├── .env.example
└── README.md
```

---

## Endpoints principales

| Método | Ruta                          | Descripción                       | Auth         |
|--------|-------------------------------|-----------------------------------|--------------|
| POST   | `/api/token/`                 | Obtener JWT (login)               | No           |
| POST   | `/api/token/refresh/`         | Renovar access token              | No           |
| GET    | `/admin/`                     | Panel de administración Django    | Session      |
| POST   | `/api/promociones/obtener/`   | Consultar promociones             | JWT Bearer   |
| GET    | `/api/general/health/`        | Health check                      | No           |

Autenticación: `Authorization: Bearer <access_token>`

---

## Patrón LogService

Todas las vistas deben usar `LogService` para auditoría:

```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 — Limpieza de datos
            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 — Acción
            resultado = mi_accion(params)
            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` registra automáticamente en la tabla `audit_logs` el usuario, IP, path, request/response y status code.

---

## Flujo de ramas

```
pre-dev  →  dev  →  master
```

- `pre-dev`: desarrollo activo, integración de features
- `dev`: validación previa a producción
- `master`: rama de producción estable

```bash
# Crear feature
git checkout pre-dev
git checkout -b feature/mi-feature

# Mergear a pre-dev
git checkout pre-dev
git merge feature/mi-feature --no-ff

# Promover a dev
git checkout dev
git merge pre-dev --no-ff

# Promover a master
git checkout master
git merge dev --no-ff
```

---

## Mantenimiento

```bash
# Limpiar sesiones expiradas
cd app && python manage.py clearsessions

# Ver estado de la BD
cd app && python manage.py dbshell

# Backup SQLite (desarrollo)
cp app/data/db.sqlite3 app/data/db.sqlite3.bak

# Backup PostgreSQL (producción)
pg_dump -U postgres vencorelab > backup_$(date +%Y%m%d).sql

# Actualizar dependencias
pip list --outdated
pip install -U <paquete>
pip freeze > deployments/requirements.txt

# Reiniciar contenedor Docker
docker-compose restart web

# Ver logs del contenedor
docker-compose logs -f web --tail=100
```

---

> **V-Encore Lab** — Sistema Automatizado v1.0  
> Repositorio: `Proyecto-SaaS/django-core-base`
