Flujo de Negocio: CRM
Modulo: crm
Modelo Principal: crm.lead
Aplica Workflow: Si
1. Tipos de Registro
| Tipo |
Descripcion |
Uso |
| lead |
Lead |
Pre-calificado, investigacion |
| opportunity |
Opportunity |
Calificado, proceso de venta |
2. Estados de Oportunidad (won_status)
| Estado |
Descripcion |
Condicion |
| pending |
Pendiente |
Cualquier caso no cerrado |
| won |
Ganada |
probability=100 AND stage.is_won=True |
| lost |
Perdida |
active=False AND probability=0 |
3. Diagrama de Flujo Lead → Opportunity
┌──────────────────┐
│ CREAR LEAD │
│ type='lead' │
│ stage='New' │
└────────┬─────────┘
│
[Investigacion/Calificacion]
│
▼
┌──────────────────┐
│ CONVERTIR A │
│ OPPORTUNITY │
└────────┬─────────┘
│
convert_opportunity()
│
▼
┌──────────────────┐
│ OPPORTUNITY │
│ type='opportunity'│
│ date_conversion │
└────────┬─────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
[Negociacion] [Propuesta] [Cierre]
│ │ │
└─────────────────┼─────────────────┘
│
┌──────────────────┴──────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ GANADA │ │ PERDIDA │
│ action_set_won()│ │ action_set_lost()│
│ │ │ │
│ - probability=100│ │ - probability=0 │
│ - stage.is_won │ │ - active=False │
│ - won_status=won │ │ - won_status=lost│
│ - date_closed │ │ - lost_reason_id │
└──────────────────┘ └──────────────────┘
4. Pipeline de Etapas
ETAPAS POR DEFECTO:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ New │──►│ Qualified│──►│Proposition│──►│ Won │
│ seq=1 │ │ seq=2 │ │ seq=3 │ │ seq=70 │
│ │ │ │ │ │ │ is_won ✓ │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│
probability = 100
won_status = 'won'
5. Metodos de Transicion
action_set_won()
PROPOSITO: Marcar oportunidad como ganada
PROCESO:
1. Desarchiva lead (si estaba archivada)
2. Agrupa leads por etapa ganadora
3. Para cada grupo:
- Busca etapa con is_won=True
- Selecciona mejor etapa (sequence mas cercana)
4. Escribe stage_id y probability=100
EFECTOS:
- probability = 100
- stage_id = etapa ganadora
- won_status = 'won' (computed)
- date_closed = ahora
action_set_lost(**additional_values)
PROPOSITO: Marcar oportunidad como perdida
PROCESO:
1. Archiva la lead (active=False)
2. Escribe additional_values (ej: lost_reason_id)
3. Establece probability=0, automated_probability=0
EFECTOS:
- active = False
- probability = 0
- won_status = 'lost' (computed)
- date_closed = ahora
- lost_reason_id = razon
convert_opportunity(partner, user_ids, team_id)
PROPOSITO: Convertir lead a opportunity
PROCESO:
1. Para cada lead activa no ganada:
- Prepara datos de conversion
- Escribe cambios
2. Asigna vendedores (round-robin)
DATOS CONVERSION:
- type = 'opportunity'
- date_conversion = ahora
- partner_id = cliente
- stage_id = etapa inicial
merge_opportunity(user_id, team_id, auto_unlink)
PROPOSITO: Fusionar oportunidades duplicadas
PROCESO:
1. Ordena por nivel de confianza
2. La primera es el resultado
3. Fusiona datos de las otras
4. Transfiere dependencias
5. Elimina registros mergeados
CRITERIOS ORDENAMIENTO:
- No archivadas > archivadas
- Opportunity > lead
- Mayor sequence en stage
- Mayor probability
- Mayor ID
6. Predictive Lead Scoring (PLS)
CALCULO DE PROBABILIDAD:
1. RECOPILAR FRECUENCIAS
└─ crm.lead.scoring.frequency
└─ Por cada (variable, value):
- won_count
- lost_count
2. CALCULAR PROBABILIDADES BASE
P(Won) = total_won / total
P(Lost) = total_lost / total
3. PARA CADA CAMPO A, B, C:
P(A|Won) = (won_count_A + 0.1) / (total_won + 0.1*n)
P(A|Lost) = (lost_count_A + 0.1) / (total_lost + 0.1*n)
4. NAIVE BAYES:
S(Won) = P(A|Won) * P(B|Won) * P(C|Won) * P(Won)
S(Lost) = P(A|Lost) * P(B|Lost) * P(C|Lost) * P(Lost)
5. RESULTADO:
automated_probability = S(Won) / (S(Won) + S(Lost)) * 100
7. Flujo de Probabilidades
LEAD CREADA
│
├─ probability = 0 (inicial)
│
▼
CAMBIOS EN CAMPOS PLS
│
├─ _compute_probabilities()
├─ automated_probability recalculada
│
├─ Si is_automated_probability == True:
│ └─ probability = automated_probability
│
├─ Si is_automated_probability == False:
│ └─ probability mantiene valor manual
│
▼
CIERRE
│
├─ action_set_won():
│ └─ probability = 100 (forzado)
│
└─ action_set_lost():
└─ probability = 0 (forzado)
8. Reglas de Negocio
| ID |
Regla |
Validacion |
Mensaje |
| R1 |
Probability range |
0 <= probability <= 100 |
Probability invalida |
| R2 |
Won stage check |
is_won implica probability=100 |
Inconsistencia estado |
| R3 |
Lead requires team |
Si use_leads en team |
Equipo sin leads |
| R4 |
Partner on convert |
partner_id al convertir |
Cliente requerido |
9. Acciones Automaticas
| Trigger |
Accion |
Condicion |
| stage_id change |
Recalcular PLS |
Siempre |
| Campo PLS change |
Recalcular automated_prob |
Siempre |
| action_set_won |
Actualizar frecuencias |
Para PLS |
| action_set_lost |
Actualizar frecuencias |
Para PLS |
| Asignacion user_id |
date_open = ahora |
Primera asignacion |
| Cierre |
date_closed = ahora |
won o lost |
10. Asignacion Automatica de Leads
CRON: ir_cron_crm_lead_assign
PROCESO:
1. Buscar leads sin asignar
2. Por cada equipo con assignment_enabled:
- Filtrar por assignment_domain
3. Por cada miembro:
- Verificar assignment_optout = False
- Verificar capacidad (assignment_max)
- Aplicar assignment_domain_preferred
4. Distribuir round-robin
EJEMPLO ROUND-ROBIN:
4 vendedores (S1-S4) para 6 leads (L1-L6):
S1 → L1, L5
S2 → L2, L6
S3 → L3
S4 → L4
11. Deteccion de Duplicados
CRITERIOS:
- Email normalizado exacto
- Phone sanitized exacto
- Mismo partner_id
METODO: _get_lead_duplicates(partner, email, include_lost)
USO:
- En wizard de conversion
- Para sugerir merge
- Filtro: activas y pendientes (o todas si include_lost)
12. Permisos por Estado
| Accion |
Grupo Requerido |
| Crear lead |
group_sale_salesman |
| Convertir a opp |
group_sale_salesman |
| Marcar ganada |
group_sale_salesman |
| Marcar perdida |
group_sale_salesman |
| Merge leads |
group_sale_salesman |
| Config equipo |
group_sale_manager |
Referencias:
- crm_lead.py: action_set_won, action_set_lost, convert_opportunity
- crm_stage.py: etapas y is_won
- crm_lead_scoring_frequency.py: PLS