Pular para o conteúdo

Bitconn WhatsApp Scheduler

Productivity/WhatsApp · v19.0.1.1.0 · GPL-2

Permite agendar envios de mensagens WhatsApp usando templates aprovados.

  • Criação de agendamentos com data/hora definida
  • Seleção de template e conta WhatsApp
  • Cron de processamento automático dos envios
  • Visão de lista para agentes com filtros e agrupamentos

whatsapp, crm, survey

Módulo para agendamento e envio automatizado de mensagens WhatsApp via templates aprovados no Meta Business.

Depende do módulo Enterprise whatsapp e do módulo crm.



  1. Instale as dependências Python no virtualenv:
    Terminal window
    pip install phonenumbers
  2. Certifique-se que os módulos whatsapp e crm estão instalados no Odoo.
  3. Instale o módulo bitconn_whatsapp pela interface ou via linha de comando:
    Terminal window
    ./odoo-bin -c <seu.conf> -i bitconn_whatsapp

O módulo usa um cron job que executa a cada 5 minutos e processa todos os registros do modelo bitconn.whatsapp.schedule que estejam:

  • state = 'scheduled'
  • scheduled_date <= agora

Para cada registro encontrado, o cron chama _send_whatsapp(), que usa o whatsapp.composer do módulo Enterprise para efetuar o envio via API do Meta (WhatsApp Cloud API).

[Cron a cada 5min]
_process_scheduled_messages()
├─ busca: state=scheduled AND scheduled_date <= now
└─ para cada registro:
_send_whatsapp()
├─ cria whatsapp.composer
├─ chama _send_whatsapp_template()
├─ registra whatsapp.message gerada
├─ atualiza state → 'sent'
└─ posta nota no chatter do lead (se vinculado)

⚠️ Importante: O cron do Odoo não garante envio no segundo exato. O desvio máximo de atraso é o intervalo do cron (padrão: 5 minutos).

Intervalo do cronAtraso máximo
5 minutos (padrão)até 5 min
1 minutoaté 1 min
30 segundos*até 30 seg

* O Odoo suporta interval_type = 'seconds' mas intervalos muito curtos aumentam carga no servidor.

Para aumentar a precisão, altere o intervalo do cron em:
Configurações → Técnico → Automação → Ações Agendadas → “Bitconn WhatsApp: Processar Envios Agendados”

Ou diretamente no XML de dados (data/ir_cron_data.xml):

<field name="interval_number">1</field>
<field name="interval_type">minutes</field>

Se houver muitos agendamentos simultâneos, os envios serão processados sequencialmente dentro do mesmo tick do cron. Para alto volume, considere processar em lotes com limit:

# Sobrescreva _process_scheduled_messages para processar em lotes de 50
def _process_scheduled_messages(self):
now = fields.Datetime.now()
schedules = self.search([
('state', '=', 'scheduled'),
('scheduled_date', '<=', now),
], limit=50)
for schedule in schedules:
schedule._send_whatsapp()

Tipo: método de botão (UI)
Modelo: bitconn.whatsapp.schedule

Transição draft → scheduled. Valida que o registro está em rascunho e registra nota interna no chatter do lead vinculado (se houver).

schedule.action_schedule()

Tipo: método de botão (UI)
Modelo: bitconn.whatsapp.schedule

Cancela um agendamento que ainda não foi enviado. Impede cancelamento de registros sent.


Tipo: método de botão (UI)
Modelo: bitconn.whatsapp.schedule

Redefine agendamentos cancelled ou failed de volta para draft, limpando o erro e a mensagem vinculada.


Tipo: método privado — chamado pelo Cron
Modelo: bitconn.whatsapp.schedule

Ponto de entrada do cron. Busca todos os agendamentos pendentes e delega o envio para _send_whatsapp().

# Chamada pelo cron:
# model._process_scheduled_messages()
# Pode ser chamado manualmente via shell para testes:
env['bitconn.whatsapp.schedule']._process_scheduled_messages()

Tipo: método privado — chamado por _process_scheduled_messages
Modelo: bitconn.whatsapp.schedule

Executa o envio de um único agendamento:

  1. Cria um whatsapp.composer com a conta, template e número
  2. Chama _send_whatsapp_template() (API Meta via módulo Enterprise)
  3. Vincula o whatsapp.message gerado ao agendamento
  4. Atualiza state → 'sent' ou state → 'failed' em caso de erro
  5. Posta nota no chatter do lead vinculado

Tipo: método de botão (UI)
Modelo: crm.lead

Abre o wizard de criação de agendamento pré-preenchido com os dados do lead (nome, contato, telefone). Disponível no formulário do lead via botão “Agendar WhatsApp”.


Tipo: método de botão (UI)
Modelo: crm.lead

Abre a lista de agendamentos filtrada pelo lead. Acessível pelo smart button com contador no formulário do lead.


draft
├─[action_schedule]──► scheduled ──[cron _process_scheduled_messages]──► sent
│ │
│ [action_cancel]
│ │
│ ▼
│ cancelled ──[action_reset_draft]──► draft
└─────────────────────────────────────────────────────────────► failed ──[action_reset_draft]──► draft

  1. Acesse WhatsApp → Agendamentos → Novo
  2. Preencha: descrição, número, conta WhatsApp, template e data/hora
  3. Clique em “Agendar Envio”
  4. O cron processará automaticamente no próximo tick após a data agendada

Ou diretamente do CRM:

  1. Abra um Lead/Oportunidade
  2. Clique no botão “Agendar WhatsApp” no header do formulário
  3. O wizard abrirá pré-preenchido com os dados do lead
  4. Selecione o template, conta e data/hora
  5. Clique em “Confirmar Agendamento”

É possível criar agendamentos automaticamente com Regras de Automação (base_automation) do Odoo, sem escrever código.

Exemplo: agendar WhatsApp quando um lead muda para a etapa “Proposta”

Seção intitulada “Exemplo: agendar WhatsApp quando um lead muda para a etapa “Proposta””

Configurações → Técnico → Automação → Regras de Automação → Novo

CampoValor
NomeAgendar WhatsApp na Proposta
ModeloLead/Oportunidade (crm.lead)
GatilhoAo atualizar um registro
Campos monitoradosstage_id
AçãoExecutar código Python

Código Python da ação:

# Busca a conta WhatsApp e o template desejados
wa_account = env['whatsapp.account'].search([], limit=1)
template = env['whatsapp.template'].search([
('name', 'ilike', 'proposta'),
('wa_account_id', '=', wa_account.id),
('status', '=', 'approved'),
], limit=1)
if wa_account and template:
for lead in records:
phone = lead.partner_id.phone or lead.phone or lead.mobile
if not phone:
continue
schedule = env['bitconn.whatsapp.schedule'].create({
'name': f'WhatsApp Proposta - {lead.name}',
'lead_id': lead.id,
'partner_id': lead.partner_id.id if lead.partner_id else False,
'mobile_number': phone,
'whatsapp_account_id': wa_account.id,
'template_id': template.id,
# Enviar 1 hora após a mudança de etapa
'scheduled_date': datetime.datetime.now() + datetime.timedelta(hours=1),
'state': 'scheduled',
})

Nota: datetime já está disponível no contexto das regras de automação do Odoo.


Exemplo: agendar WhatsApp de follow-up 3 dias após criação do lead

Seção intitulada “Exemplo: agendar WhatsApp de follow-up 3 dias após criação do lead”
CampoValor
GatilhoBaseado em data/tempo
DataData de Criação
Atraso+3 dias
AçãoExecutar código Python
wa_account = env['whatsapp.account'].search([], limit=1)
template = env['whatsapp.template'].search([
('name', 'ilike', 'follow'),
('wa_account_id', '=', wa_account.id),
('status', '=', 'approved'),
], limit=1)
if wa_account and template:
for lead in records:
phone = lead.partner_id.phone or lead.phone or lead.mobile
if not phone:
continue
# Cria já agendado para envio imediato (o cron irá processar no próximo tick)
env['bitconn.whatsapp.schedule'].create({
'name': f'Follow-up D+3 - {lead.name}',
'lead_id': lead.id,
'partner_id': lead.partner_id.id if lead.partner_id else False,
'mobile_number': phone,
'whatsapp_account_id': wa_account.id,
'template_id': template.id,
'scheduled_date': datetime.datetime.now(),
'state': 'scheduled',
})

Use este padrão em qualquer método de modelo, wizard ou script de migração:

def meu_metodo(self):
wa_account = self.env['whatsapp.account'].browse(ACCOUNT_ID)
template = self.env['whatsapp.template'].browse(TEMPLATE_ID)
schedule = self.env['bitconn.whatsapp.schedule'].create({
'name': 'Descrição do agendamento',
'lead_id': self.id, # opcional
'partner_id': self.partner_id.id, # opcional
'mobile_number': '+5511999999999',
'whatsapp_account_id': wa_account.id,
'template_id': template.id,
'scheduled_date': fields.Datetime.now() + timedelta(hours=2),
'state': 'scheduled', # já agendado, pronto para o cron
})
return schedule
schedule = self.env['bitconn.whatsapp.schedule'].create({...})
schedule._send_whatsapp()

Use com cautela em contextos de UI — pode deixar a interface lenta se o envio demorar. Prefira o cron para produção.


bitconn_whatsapp/
├── __init__.py
├── __manifest__.py
├── data/
│ └── ir_cron_data.xml # Definição do cron (a cada 5 min)
├── models/
│ ├── __init__.py
│ ├── whatsapp_schedule.py # Modelo principal + lógica de envio
│ └── crm_lead.py # Extensão do crm.lead (smart button + wizard action)
├── wizards/
│ ├── __init__.py
│ └── whatsapp_schedule_wizard.py # Wizard de agendamento a partir do lead
├── security/
│ └── ir.model.access.csv # Permissões de acesso
└── views/
├── whatsapp_schedule_views.xml # Form, list, search do agendamento
├── whatsapp_schedule_wizard_views.xml # Form do wizard
├── crm_lead_views.xml # Extensão do formulário do lead
└── whatsapp_schedule_menus.xml # Menu WhatsApp → Agendamentos