Flujo de Negocio: Base (Kernel)
Modulo: base
Aplica Workflow: Parcial (no tiene estados tradicionales, pero tiene flujos importantes)
1. Nota sobre Workflows en Base
El modulo base no implementa workflows de estados tradicionales como otros modulos
(sale, purchase, stock). Sin embargo, tiene flujos de negocio criticos:
- Autenticacion de usuarios
- Control de acceso por reglas
- Ciclo de tareas programadas (cron)
- Jerarquia de permisos y grupos
2. Flujo de Autenticacion (res.users)
2.1 Diagrama de Autenticacion
┌─────────────────────────────────────────────────────────────────────┐
│ SOLICITUD DE AUTENTICACION │
│ (login + password + context) │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ VERIFICAR COOLDOWN │
│ - Consultar intentos fallidos recientes │
│ - Si > 5 fallos en ultimos 60s: RECHAZAR │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ BUSCAR USUARIO │
│ - Buscar por login │
│ - Verificar usuario activo │
└─────────────────────────────────┬───────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ USUARIO EXISTE │ │ NO EXISTE │
│ Y ACTIVO │ │ O INACTIVO │
└────────┬────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────┐
│ VALIDAR CREDENCIALES │ │ ACCESS DENIED │
│ - Comparar hash password │ │ + Log intento │
│ - pbkdf2_sha512 (600k rounds) │ └─────────────────┘
└─────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ PASSWORD OK │ │ PASSWORD FAIL │
└────────┬────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ ACTUALIZAR SESSION │ │ REGISTRAR FALLO │
│ - Generar session_token │ │ - Incrementar contador │
│ - Registrar login_date │ │ - Verificar cooldown │
│ - Actualizar log │ └────────────┬────────────┘
└────────────┬────────────┘ │
│ ▼
▼ ┌─────────────────┐
┌─────────────────┐ │ ACCESS DENIED │
│ AUTH SUCCESS │ └─────────────────┘
│ (uid, method) │
└─────────────────┘
2.2 Configuracion Anti-Brute-Force
| Parametro |
Valor Default |
Descripcion |
| Intentos maximos |
5 |
Antes de activar cooldown |
| Tiempo cooldown |
60 segundos |
Espera despues de exceder intentos |
| Configurable via |
ir.config.parameter |
auth_login_cooldown_* |
3. Flujo de Control de Acceso (ir.rule)
3.1 Diagrama de Evaluacion de Reglas
┌─────────────────────────────────────────────────────────────────────┐
│ SOLICITUD DE ACCESO A REGISTRO │
│ (modelo, registro, modo: read/write/create/unlink) │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ BUSCAR REGLAS APLICABLES │
│ - Filtrar por modelo │
│ - Filtrar por modo (perm_read, perm_write, etc.) │
│ - Filtrar activas │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ SEPARAR REGLAS │
│ - GLOBALES: sin grupos asignados │
│ - POR GRUPO: con grupos asignados │
└─────────────────────────────────┬───────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ EVALUAR GLOBALES│ │ EVALUAR GRUPO │
│ (AND) │ │ (OR) │
│ │ │ │
│ Todas deben │ │ Al menos una │
│ cumplirse │ │ debe cumplirse │
└────────┬────────┘ └────────┬────────┘
│ │
└───────────┬───────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ COMBINAR RESULTADOS │
│ FINAL = GLOBALES AND GRUPO │
└─────────────────────────────────┬───────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ ACCESO PERMITIDO│ │ ACCESO DENEGADO │
└─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────────┐
│ AccessError │
│ - Regla que falla │
│ - Registro afectado │
└─────────────────────┘
3.2 Ejemplo de Evaluacion
Usuario: user_sales (grupo: sales_team.group_sale_salesman)
Reglas para model sale.order:
- R1 (global): domain = [('company_id','in',company_ids)]
- R2 (group: group_sale_salesman): domain = [('user_id','=',user.id)]
- R3 (group: group_sale_manager): domain = [] (sin restriccion)
Evaluacion para user_sales:
1. GLOBALES: R1 debe cumplirse
2. GRUPO: R2 OR R3 - pero user_sales solo tiene group_sale_salesman
Entonces solo R2 aplica
3. FINAL: R1 AND R2
= [('company_id','in',company_ids)] AND [('user_id','=',user.id)]
4. Flujo de Tareas Programadas (ir.cron)
4.1 Diagrama de Ciclo de Cron
┌─────────────────────────────────────────────────────────────────────┐
│ ESTADO INICIAL │
│ active=True, nextcall=DateTime, failure_count=0 │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ SISTEMA DETECTA │
│ nextcall <= ahora │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ ADQUIRIR JOB │
│ - Lock en BD (FOR UPDATE SKIP LOCKED) │
│ - Marcar como en ejecucion │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ EJECUTAR │
│ - Nuevo contexto con user_id │
│ - Ejecutar ir.actions.server │
└─────────────────────────────────┬───────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ EXITO │ │ FALLO │
│ │ │ │
│ lastcall = ahora│ │ failure_count++ │
│ failure_count=0 │ │ first_failure │
│ first_failure= │ │ = ahora │
│ None │ │ (si primero) │
└────────┬────────┘ └────────┬────────┘
│ │
│ ▼
│ ┌─────────────────────────────────┐
│ │ VERIFICAR DESACTIVACION │
│ │ Si failure_count >= 5 │
│ │ AND (ahora - first_failure) >= 7d│
│ └─────────────┬───────────────────┘
│ │
│ ┌─────────────┴─────────────┐
│ │ │
│ ▼ ▼
│ ┌─────────────────┐ ┌─────────────────┐
│ │ NO DESACTIVAR │ │ DESACTIVAR │
│ │ (< 5 fallos o │ │ active = False │
│ │ < 7 dias) │ └────────┬────────┘
│ └────────┬────────┘ │
│ │ │
└────────────┼───────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ CALCULAR SIGUIENTE EJECUCION │
│ nextcall = lastcall + relativedelta(interval) │
│ Minimo: 5 horas entre intentos si hay fallos │
└─────────────────────────────────────────────────────────────────────┘
4.2 Tabla de Estados de Cron
| Estado |
active |
failure_count |
first_failure_date |
Descripcion |
| Normal |
True |
0 |
None |
Funcionando correctamente |
| Fallo temporal |
True |
1-4 |
Set |
Reintentos pendientes |
| Desactivado |
False |
>= 5 |
>= 7 dias |
Requiere intervencion manual |
4.3 Intervalo de Ejecucion
| Tipo |
Valor |
| minutes |
Cada X minutos |
| hours |
Cada X horas |
| days |
Cada X dias |
| weeks |
Cada X semanas |
| months |
Cada X meses |
5. Flujo de Jerarquia de Grupos (res.groups)
5.1 Diagrama de Implicaciones
┌─────────────────────────────────────────────────────────────────────┐
│ USUARIO ASIGNADO A GRUPO │
│ user.group_ids = [group_A] │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ RESOLVER IMPLICACIONES │
│ Si group_A.implied_ids = [group_B, group_C] │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ RESOLVER TRANSITIVAMENTE │
│ Si group_B.implied_ids = [group_D] │
│ Entonces: A → B → D (A implica D) │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ GRUPOS EFECTIVOS │
│ user.all_group_ids = [group_A, group_B, group_C, group_D] │
└─────────────────────────────────────────────────────────────────────┘
Ejemplo visual:
group_sale_manager
│
├── implied_ids ──► group_sale_salesman
│ │
│ └── implied_ids ──► group_sale_salesman_all_leads
│
└── implied_ids ──► group_user
Usuario con group_sale_manager tiene:
- group_sale_manager (explicito)
- group_sale_salesman (implicado)
- group_sale_salesman_all_leads (transitivo)
- group_user (implicado)
5.2 Grupos Excluyentes (Disjoint)
┌──────────────────┐ DISJOINT ┌──────────────────┐
│ group_user │◄────────────────►│ group_portal │
│ (Interno) │ │ (Portal) │
└────────┬─────────┘ └─────────┬────────┘
│ DISJOINT │
└──────────────────┬─────────────────────┘
│
▼
┌──────────────────┐
│ group_public │
│ (Publico) │
└──────────────────┘
REGLA: Un usuario solo puede pertenecer a UNO de estos grupos.
- Si es group_user: usuario interno (empleado)
- Si es group_portal: usuario externo (cliente/proveedor)
- Si es group_public: usuario anonimo
6. Flujo de Sincronizacion Partner-Usuario
6.1 Diagrama de Sincronizacion
┌─────────────────────────────────────────────────────────────────────┐
│ CAMBIO EN RES.PARTNER │
│ Campos: name, email, phone, active, etc. │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ PROPAGAR A RES.USERS │
│ Si partner tiene usuarios vinculados (user_ids) │
│ Entonces actualizar campos relacionados en usuario │
└─────────────────────────────────────────────────────────────────────┘
Y
┌─────────────────────────────────────────────────────────────────────┐
│ CAMBIO EN RES.USERS │
│ Campos: name, email, active, etc. │
└─────────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ PROPAGAR A RES.PARTNER │
│ Actualizar partner_id con nuevos valores │
└─────────────────────────────────────────────────────────────────────┘
RESTRICCION:
- Si partner.active = False y tiene usuarios internos activos
→ Error: no se puede archivar
7. Reglas de Negocio
| ID |
Regla |
Validacion |
Mensaje Error |
| R1 |
Usuario admin no eliminable |
res.users.unlink |
No se puede eliminar admin |
| R2 |
Partner con usuarios no archivable |
res.partner.write |
Partner tiene usuarios activos |
| R3 |
Grupos excluyentes |
res.users._check_disjoint |
Usuario en grupos disjuntos |
| R4 |
Empresa no puede cambiar padre |
res.company.write |
No se puede cambiar jerarquia |
| R5 |
Secuencia step != 0 |
ir.sequence.create |
Step no puede ser cero |
| R6 |
Cron requiere accion |
ir.cron.create |
Debe tener accion servidor |
8. Acciones Automaticas
| Trigger |
Accion |
Condicion |
| res.users.create |
Crear partner |
Si no existe partner_id |
| res.users.write(active=False) |
Archivar partner |
Si no tiene otros usuarios activos |
| res.company.create |
Crear partner |
Automatico |
| ir.cron.nextcall reached |
Ejecutar accion |
active=True |
| res.currency > 1 active |
Activar grupo multimoneda |
Automatico |
9. Permisos por Modelo
| Modelo |
Grupo Minimo |
Notas |
| res.partner |
group_user |
Lectura para portal |
| res.users |
group_system |
Solo admin |
| res.company |
group_user |
Lectura propia empresa |
| res.groups |
group_system |
Solo admin |
| ir.rule |
group_system |
Solo admin |
| ir.cron |
group_system |
Solo admin |
Referencias:
- Archivo principal:
models/res_users.py, models/ir_rule.py, models/ir_cron.py
- Seguridad:
security/base_security.xml