# 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: 1. **Autenticacion de usuarios** 2. **Control de acceso por reglas** 3. **Ciclo de tareas programadas (cron)** 4. **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`