PHPackages                             bellinatiperez/bpmessage-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. bellinatiperez/bpmessage-bundle

ActiveMautic-plugin[Mail &amp; Notifications](/categories/mail)

bellinatiperez/bpmessage-bundle
===============================

Mautic plugin for sending SMS, WhatsApp and RCS messages via BpMessage API in batch mode

0.0.46(3mo ago)03561GPL-3.0-or-laterPHP

Since Nov 8Pushed 3mo agoCompare

[ Source](https://github.com/bellinatiperez/mautic-bpmessage-bundle)[ Packagist](https://packagist.org/packages/bellinatiperez/bpmessage-bundle)[ RSS](/packages/bellinatiperez-bpmessage-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (45)Used By (1)

MauticBpMessageBundle
=====================

[](#mauticbpmessagebundle)

Plugin para Mautic que integra com a API BpMessage para envio de mensagens SMS, WhatsApp, RCS e Emails em lote.

📋 Índice
--------

[](#-índice)

- [Características](#caracter%C3%ADsticas)
- [Requisitos](#requisitos)
- [Instalação](#instala%C3%A7%C3%A3o)
- [Configuração](#configura%C3%A7%C3%A3o)
- [Ações de Campanha](#a%C3%A7%C3%B5es-de-campanha)
- [Comandos CLI](#comandos-cli)
- [Estrutura do Banco de Dados](#estrutura-do-banco-de-dados)
- [Unicidade de Lotes](#unicidade-de-lotes)
- [Fluxo de Funcionamento](#fluxo-de-funcionamento)
- [Troubleshooting](#troubleshooting)
- [Desenvolvimento](#desenvolvimento)

🚀 Características
-----------------

[](#-características)

- ✅ **3 Tipos de Ação**: SMS/WhatsApp/RCS, Email Personalizado e Email Template
- ✅ **Envio em Lote**: Agrupa mensagens para envio otimizado (até 5000 por lote)
- ✅ **Múltiplos Canais**: Suporta SMS, WhatsApp, RCS e Email
- ✅ **Integração com Campanhas**: 3 ações nativas no Campaign Builder do Mautic
- ✅ **Tokens Dinâmicos**: Use `{contactfield=fieldname}` para personalizar mensagens
- ✅ **Gestão de Filas**: Sistema robusto de filas com retry automático
- ✅ **Configuração Flexível**: Controle de tamanho de lote e janela de tempo
- ✅ **Templates do Mautic**: Use templates de email existentes do Mautic
- ✅ **SQL Fallback**: Garante persistência durante batch processing
- ✅ **Unicidade de Lotes**: Lotes únicos por configuração (quota + service + type)
- ✅ **Force Close**: Comando para processar lotes imediatamente
- ✅ **Logs Detalhados**: Auditoria completa de todas as operações
- ✅ **CLI Commands**: Comandos para processar filas e fazer limpeza

📦 Requisitos
------------

[](#-requisitos)

- Mautic 4.x ou 5.x
- PHP 7.4+ ou 8.0+
- MySQL 5.7+ ou MariaDB 10.2+
- Conta ativa na API BpMessage
- Credenciais da API BpMessage

🔧 Instalação
------------

[](#-instalação)

### 1. Copiar Plugin

[](#1-copiar-plugin)

```
cd /path/to/mautic
cp -r MauticBpMessageBundle plugins/
```

### 2. Limpar Cache

[](#2-limpar-cache)

```
php bin/console cache:clear
```

### 3. Instalar no Mautic

[](#3-instalar-no-mautic)

1. Acesse Mautic Admin → Plugins
2. Clique em "Install/Upgrade Plugins"
3. O plugin "BpMessage" aparecerá na lista
4. Clique para publicar

### 4. Criar Tabelas do Banco

[](#4-criar-tabelas-do-banco)

```
php bin/console doctrine:schema:update --force
```

Ou manualmente:

```
CREATE TABLE bpmessage_lot (
    id INT AUTO_INCREMENT PRIMARY KEY,
    external_lot_id VARCHAR(255),
    name VARCHAR(255) NOT NULL,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    user_cpf VARCHAR(14) NOT NULL,
    id_quota_settings INT NOT NULL,
    id_service_settings INT NOT NULL,
    service_type INT NULL,
    id_book_business_send_group INT NULL,
    image_url TEXT NULL,
    image_name VARCHAR(255) NULL,
    status VARCHAR(20) NOT NULL,
    messages_count INT DEFAULT 0,
    created_at DATETIME NOT NULL,
    finished_at DATETIME NULL,
    campaign_id INT NULL,
    api_base_url VARCHAR(255) NOT NULL,
    batch_size INT NOT NULL,
    time_window INT NOT NULL,
    error_message TEXT NULL,
    INDEX idx_status (status),
    INDEX idx_created_at (created_at),
    INDEX idx_campaign_id (campaign_id)
);

CREATE TABLE bpmessage_queue (
    id INT AUTO_INCREMENT PRIMARY KEY,
    lot_id INT NOT NULL,
    lead_id INT NOT NULL,
    payload_json TEXT NOT NULL,
    status VARCHAR(20) NOT NULL,
    retry_count SMALLINT DEFAULT 0,
    error_message TEXT NULL,
    created_at DATETIME NOT NULL,
    sent_at DATETIME NULL,
    FOREIGN KEY (lot_id) REFERENCES bpmessage_lot(id) ON DELETE CASCADE,
    FOREIGN KEY (lead_id) REFERENCES leads(id) ON DELETE CASCADE,
    INDEX idx_lot_status (lot_id, status),
    INDEX idx_created_at (created_at),
    INDEX idx_status (status)
);
```

### 5. Configurar Cron

[](#5-configurar-cron)

Adicione ao crontab para processar as filas:

```
# Processar filas a cada 5 minutos
*/5 * * * * php /path/to/mautic/bin/console mautic:bpmessage:process

# Limpar lotes antigos uma vez por semana (opcional)
0 2 * * 0 php /path/to/mautic/bin/console mautic:bpmessage:cleanup --days=30
```

⚙️ Configuração
---------------

[](#️-configuração)

### 1. Configurar Plugin no Mautic

[](#1-configurar-plugin-no-mautic)

1. Acesse **Settings** → **Plugins** → **BpMessage**
2. Configure:
    - **API Base URL**: URL da API (ex: `https://api.bpmessage.com.br`)
    - **Default Batch Size**: Tamanho padrão de lote (padrão: 1000)
    - **Default Time Window**: Janela de tempo padrão em segundos (padrão: 300)
3. Clique em **Save &amp; Close**
4. Marque como **Published**

### 2. Obter Credenciais da BpMessage

[](#2-obter-credenciais-da-bpmessage)

Você precisará obter as seguintes informações da BpMessage:

- **ID Quota Settings**: ID da cota disponível
- **ID Service Settings**: ID da rota de envio

Para obter IDs de cota e rota, consulte o endpoint da BpMessage:

```
GET /api/ServiceSettings/GetRoutes

```

📱 Ações de Campanha
-------------------

[](#-ações-de-campanha)

O plugin oferece **3 tipos de ação** para campanhas:

### 1. Send BpMessage (SMS/WhatsApp/RCS)

[](#1-send-bpmessage-smswhatsapprcs)

Envia mensagens de texto via SMS, WhatsApp ou RCS.

**Configuração:**

- **ID Quota Settings**: ID da cota (obrigatório, deve ser &gt; 0)
- **ID Service Settings**: ID da rota (obrigatório, deve ser &gt; 0)
- **Service Type**:
    - `1` = SMS
    - `2` = WhatsApp (padrão)
    - `3` = RCS
- **Batch Size**: Tamanho do lote (padrão: 1000, máx: 5000)
- **Time Window**: Tempo em segundos (padrão: 300)

**Mapeamento de Campos:**

- **Contract Field**: Campo que contém o número do contrato
- **CPF Field**: Campo que contém o CPF/CNPJ
- **Phone Field**: Campo que contém o telefone (padrão: `mobile`)

**Exemplo de Mensagem:**

```
Olá {contactfield=firstname},

Seu contrato {contactfield=contract_number} foi atualizado.

Qualquer dúvida, entre em contato.

```

**Para RCS:**

- **Template ID**: ID do template RCS cadastrado na BpMessage

### 2. Send BpMessage Email

[](#2-send-bpmessage-email)

Envia emails personalizados via BpMessage API.

**Configuração:**

- **ID Service Settings**: ID da rota de email (obrigatório)
- **Batch Size**: Tamanho do lote (padrão: 1000)
- **Time Window**: Tempo em segundos (padrão: 300)

**Campos do Email:**

- **From**: Email do remetente (ex: `noreply@example.com`)
- **To Field**: Campo que contém o email do destinatário (padrão: `email`)
- **Subject**: Assunto do email (suporta tokens)
- **Body**: Corpo do email em HTML (suporta tokens)

**Campos Adicionais (opcionais):**

- **Contract Field**: Campo do contrato
- **CPF/CNPJ Receiver Field**: Campo do CPF/CNPJ
- **CRM ID**: ID do CRM
- **Book Business Foreign ID**: ID externo do negócio
- **Step Foreign ID**: ID externo da etapa

**Exemplo:**

```
Subject: Olá {contactfield=firstname}!

Body:

    Olá {contactfield=firstname}!
    Seu contrato {contactfield=contract_number} foi atualizado.
    Qualquer dúvida, entre em contato.

```

### 3. Send BpMessage Email Template

[](#3-send-bpmessage-email-template)

Envia emails usando templates existentes do Mautic.

**Configuração:**

- **ID Service Settings**: ID da rota de email (obrigatório)
- **Email Template**: Selecione um template de email do Mautic
- **Batch Size**: Tamanho do lote (padrão: 1000)
- **Time Window**: Tempo em segundos (padrão: 300)

**Campos Adicionais (opcionais):**

- **Contract Field**: Campo do contrato
- **CPF/CNPJ Receiver Field**: Campo do CPF/CNPJ
- **CRM ID**: ID do CRM
- **Book Business Foreign ID**: ID externo do negócio
- **Step Foreign ID**: ID externo da etapa

**Vantagens:**

- ✅ Usa editor visual do Mautic
- ✅ Templates reutilizáveis
- ✅ Tokens substituídos automaticamente
- ✅ Subject e body do template são usados

🖥️ Comandos CLI
---------------

[](#️-comandos-cli)

### Processar Filas

[](#processar-filas)

Processa lotes abertos e envia mensagens pendentes:

```
# Processar lotes que atingiram critério de fechamento
php bin/console mautic:bpmessage:process

# Forçar fechamento de TODOS os lotes abertos (útil para testes)
php bin/console mautic:bpmessage:process --force-close

# Processar lote específico
php bin/console mautic:bpmessage:process --lot-id=123

# Retentar mensagens com falha
php bin/console mautic:bpmessage:process --retry

# Retentar com máximo de 5 tentativas
php bin/console mautic:bpmessage:process --retry --max-retries=5
```

### Limpeza

[](#limpeza)

Remove lotes e mensagens antigas:

```
# Remover lotes finalizados há mais de 30 dias
php bin/console mautic:bpmessage:cleanup

# Remover lotes finalizados há mais de 60 dias
php bin/console mautic:bpmessage:cleanup --days=60

# Modo dry-run (preview)
php bin/console mautic:bpmessage:cleanup --dry-run
```

### Comandos de Teste

[](#comandos-de-teste)

```
# Criar template de teste
php bin/console mautic:bpmessage:create-test-template

# Testar todas as 3 ações com 50 contatos
php bin/console mautic:bpmessage:test-actions --contacts=50

# Testar apenas uma ação específica
php bin/console mautic:bpmessage:test-actions --action=message
php bin/console mautic:bpmessage:test-actions --action=email
php bin/console mautic:bpmessage:test-actions --action=template
```

🗄️ Estrutura do Banco de Dados
------------------------------

[](#️-estrutura-do-banco-de-dados)

### Tabela `bpmessage_lot`

[](#tabela-bpmessage_lot)

Armazena informações dos lotes:

CampoTipoDescrição`id`INTID interno`external_lot_id`VARCHAR(255)ID retornado pela API BpMessage`name`VARCHAR(255)Nome do lote`status`VARCHAR(20)Status: CREATING, OPEN, SENDING, FINISHED, FAILED`messages_count`INTQuantidade de mensagens`campaign_id`INTID da campanha`id_quota_settings`INTID da quota (0 para emails)`id_service_settings`INTID do serviço`service_type`INT1=SMS, 2=WhatsApp, 3=RCS, NULL=Email`batch_size`INTTamanho máximo do lote`time_window`INTJanela de tempo em segundos`created_at`DATETIMEData de criação`finished_at`DATETIMEData de finalização### Tabela `bpmessage_queue`

[](#tabela-bpmessage_queue)

Armazena mensagens na fila:

CampoTipoDescrição`id`INTID interno`lot_id`INTFK para bpmessage\_lot`lead_id`INTFK para leads`payload_json`TEXTPayload da mensagem em JSON`status`VARCHAR(20)PENDING, SENT, FAILED`retry_count`SMALLINTContador de tentativas`created_at`DATETIMEData de criação`sent_at`DATETIMEData de envio🔑 Unicidade de Lotes
--------------------

[](#-unicidade-de-lotes)

Os lotes são **únicos** pela combinação de:

### Para Message Lots (SMS/WhatsApp/RCS):

[](#para-message-lots-smswhatsapprcs)

- `campaign_id` - Qual campanha
- `id_quota_settings` - Qual quota
- `id_service_settings` - Qual configuração de serviço
- `service_type` - 1=SMS, 2=WhatsApp, 3=RCS

### Para Email Lots:

[](#para-email-lots)

- `campaign_id` - Qual campanha
- `id_quota_settings` - Sempre 0 (não usado para emails)
- `id_service_settings` - Qual configuração de email

**Exemplo:**

Se a mesma campanha tem 2 ações:

- Ação 1: WhatsApp (quota=1000, service=100, type=2)
- Ação 2: SMS (quota=1000, service=200, type=1)

**Resultado:** 2 lotes separados serão criados! ✅

Isso garante que:

- ✅ Mensagens com configurações diferentes não se misturam
- ✅ Cada lote é processado independentemente
- ✅ Relatórios e auditoria são precisos

🔄 Fluxo de Funcionamento
------------------------

[](#-fluxo-de-funcionamento)

```
┌─────────────────────────────────────────────────────────────┐
│              FLUXO DE ENVIO EM LOTE (SMS/WhatsApp)          │
└─────────────────────────────────────────────────────────────┘

1. CONTATO ENTRA NA CAMPANHA
   └── CampaignSubscriber::onCampaignTriggerAction()
       └── BpMessageModel::sendMessage()

2. VALIDAÇÃO
   └── MessageMapper::validateLead()
       ├── Verifica campos obrigatórios
       └── Valida formato do telefone

3. OBTER OU CRIAR LOTE
   └── LotManager::getOrCreateActiveLot()
       ├── Busca lote OPEN com mesma configuração:
       │   • campaign_id
       │   • id_quota_settings
       │   • id_service_settings
       │   • service_type
       └── Se não existe:
           ├── POST /api/Lot/CreateLot → retorna idLot
           ├── EntityManager flush()
           └── SQL UPDATE (fallback para garantir persistência)

4. MAPEAR E ENFILEIRAR MENSAGEM
   └── MessageMapper::mapLeadToMessage()
       └── LotManager::queueMessage()
           ├── Salva em bpmessage_queue (status: PENDING)
           ├── Incrementa lot.messages_count
           └── SQL UPDATE (fallback para garantir incremento)

5. PROCESSAR LOTE (VIA CRON OU --force-close)
   └── ProcessBpMessageQueuesCommand
       └── BpMessageModel::processOpenLots()
           ├── Filtra apenas message lots (idQuotaSettings > 0)
           └── Para cada lote que atingiu critério:
               ├── LotManager::sendLotMessages()
               │   └── POST /api/Lot/AddMessageToLot/{idLot}
               │       (batches de até 5000)
               └── LotManager::finishLot()
                   ├── POST /api/Lot/FinishLot/{idLot}
                   ├── lot.status = 'FINISHED'
                   ├── EntityManager flush()
                   └── SQL UPDATE (fallback para garantir FINISHED)

6. RESULTADO
   └── Status: FINISHED ✅
   └── Mensagens: SENT ✅

```

```
┌─────────────────────────────────────────────────────────────┐
│                    FLUXO DE ENVIO EMAIL                     │
└─────────────────────────────────────────────────────────────┘

1. CONTATO ENTRA NA CAMPANHA
   └── CampaignSubscriber::onCampaignTriggerAction()
       └── BpMessageEmailModel::sendEmail()
           ou BpMessageEmailTemplateModel::sendEmail()

2. VALIDAÇÃO
   └── EmailMessageMapper::validateLead()
       ├── Verifica email válido
       └── Valida campos obrigatórios

3. OBTER OU CRIAR LOTE
   └── EmailLotManager::getOrCreateActiveLot()
       ├── Busca lote OPEN com mesma configuração:
       │   • campaign_id
       │   • id_quota_settings = 0 (fixo)
       │   • id_service_settings
       └── Se não existe:
           ├── POST /api/LotEmail/CreateLotEmail → retorna idLotEmail
           ├── EntityManager flush()
           └── SQL UPDATE (fallback)

4. MAPEAR E ENFILEIRAR EMAIL
   └── EmailMessageMapper::mapLeadToEmail()
       └── EmailLotManager::queueEmail()
           ├── Salva em bpmessage_queue (status: PENDING)
           ├── Incrementa lot.messages_count
           └── SQL UPDATE (fallback)

5. PROCESSAR LOTE (VIA CRON OU --force-close)
   └── ProcessBpMessageQueuesCommand
       └── BpMessageEmailModel::processOpenLots()
           ├── Filtra apenas email lots (idQuotaSettings = 0)
           └── Para cada lote que atingiu critério:
               ├── EmailLotManager::sendLotEmails()
               │   └── POST /api/LotEmail/AddEmailToLot/{idLotEmail}
               │       (batches de até 5000)
               └── EmailLotManager::finishLot()
                   ├── POST /api/LotEmail/FinishLotEmail/{idLotEmail}
                   ├── lot.status = 'FINISHED'
                   ├── EntityManager flush()
                   └── SQL UPDATE (fallback)

6. RESULTADO
   └── Status: FINISHED ✅
   └── Emails: SENT ✅

```

### Estados do Lote

[](#estados-do-lote)

- **CREATING**: Lote está sendo criado na API BpMessage
- **OPEN**: Lote aberto, aceitando mensagens
- **SENDING**: Lote enviando mensagens para a API
- **FINISHED**: Lote finalizado com sucesso
- **FAILED**: Lote falhou durante criação

### Estados da Mensagem

[](#estados-da-mensagem)

- **PENDING**: Aguardando envio
- **SENT**: Enviada com sucesso
- **FAILED**: Falhou (será retentada até 3x)

### SQL Fallback Pattern

[](#sql-fallback-pattern)

Para garantir persistência durante batch processing do Mautic, o plugin usa SQL direto como fallback:

```
// 1. Tenta via EntityManager
$lot->setStatus('FINISHED');
$this->entityManager->flush();

// 2. Garante com SQL direto
$connection = $this->entityManager->getConnection();
$connection->executeStatement(
    'UPDATE bpmessage_lot SET status = ? WHERE id = ?',
    ['FINISHED', $lot->getId()]
);

// 3. Atualiza entidade
$this->entityManager->refresh($lot);
```

Este padrão é aplicado em:

- ✅ `createLot()` - Marcar como OPEN
- ✅ `queueMessage()` - Incrementar messages\_count
- ✅ `finishLot()` - Marcar como FINISHED

🐛 Troubleshooting
-----------------

[](#-troubleshooting)

### Mensagens não estão sendo enviadas

[](#mensagens-não-estão-sendo-enviadas)

1. **Verifique o cron**:

```
crontab -l | grep bpmessage
```

2. **Execute manualmente**:

```
php bin/console mautic:bpmessage:process --force-close -vvv
```

3. **Verifique logs**:

```
tail -f var/logs/mautic_prod.log | grep BpMessage
```

### Erro: "Configuration field 'id\_quota\_settings' must be greater than 0"

[](#erro-configuration-field-id_quota_settings-must-be-greater-than-0)

Para **message lots** (SMS/WhatsApp/RCS), o `id_quota_settings` deve ser &gt; 0.

Para **email lots**, o sistema automaticamente usa 0.

Verifique a configuração da ação na campanha.

### Lote ficou em OPEN mesmo após processar

[](#lote-ficou-em-open-mesmo-após-processar)

Este problema foi corrigido! O sistema agora usa SQL fallback para garantir que o status FINISHED seja persistido.

Se ainda ocorrer:

```
# Verificar status do lote
php bin/console ddev exec -- mysql -e "
SELECT id, status, finished_at, messages_count
FROM bpmessage_lot
WHERE id = X
"

# Forçar processamento
php bin/console mautic:bpmessage:process --lot-id=X
```

### Lotes duplicados criados

[](#lotes-duplicados-criados)

Certifique-se de que a coluna `service_type` existe no banco:

```
ALTER TABLE bpmessage_lot
ADD COLUMN service_type INT NULL AFTER id_service_settings;
```

O sistema verifica unicidade por:

- campaign\_id
- id\_quota\_settings
- id\_service\_settings
- service\_type

### Ver status dos lotes

[](#ver-status-dos-lotes)

```
-- Lotes por status
SELECT status, COUNT(*) as count, SUM(messages_count) as total_messages
FROM bpmessage_lot
GROUP BY status;

-- Lotes abertos há mais tempo
SELECT id, campaign_id, status, messages_count,
       id_quota_settings, id_service_settings, service_type,
       created_at
FROM bpmessage_lot
WHERE status = 'OPEN'
ORDER BY created_at ASC;

-- Mensagens pendentes por lote
SELECT lot_id, status, COUNT(*) as count
FROM bpmessage_queue
GROUP BY lot_id, status;

-- Verificar unicidade de lotes
SELECT campaign_id, id_quota_settings, id_service_settings,
       service_type, COUNT(*) as count
FROM bpmessage_lot
WHERE status = 'OPEN'
GROUP BY campaign_id, id_quota_settings, id_service_settings, service_type
HAVING count > 1;
```

### Forçar fechamento de lote específico

[](#forçar-fechamento-de-lote-específico)

```
php bin/console mautic:bpmessage:process --lot-id=123
```

### Limpar tudo e começar do zero

[](#limpar-tudo-e-começar-do-zero)

```
# Limpar eventos da campanha
php bin/console ddev exec -- mysql -e "DELETE FROM campaign_lead_event_log WHERE campaign_id = X"

# Limpar filas e lotes
php bin/console ddev exec -- mysql -e "DELETE FROM bpmessage_queue; DELETE FROM bpmessage_lot;"

# Limpar cache
php bin/console cache:clear

# Executar campanha novamente
php bin/console mautic:campaigns:trigger --campaign-id=X
```

🔧 Desenvolvimento
-----------------

[](#-desenvolvimento)

### Estrutura do Código

[](#estrutura-do-código)

```
MauticBpMessageBundle/
├── Command/                    # Comandos CLI
│   ├── ProcessBpMessageQueuesCommand.php
│   ├── CleanupBpMessageCommand.php
│   ├── TestBpMessageActionsCommand.php
│   └── CreateTestTemplateCommand.php
├── Config/                     # Configurações
│   ├── config.php              # Serviços e dependências
│   └── services.php            # Container config
├── Entity/                     # Entidades Doctrine
│   ├── BpMessageLot.php
│   ├── BpMessageLotRepository.php
│   ├── BpMessageQueue.php
│   └── BpMessageQueueRepository.php
├── EventListener/              # Event Subscribers
│   └── CampaignSubscriber.php
├── Form/Type/                  # Form Types
│   ├── BpMessageActionType.php
│   ├── BpMessageEmailActionType.php
│   └── BpMessageEmailTemplateActionType.php
├── Http/                       # Cliente HTTP
│   └── BpMessageClient.php
├── Integration/                # Integração Mautic
│   ├── BpMessageIntegration.php
│   └── Support/
│       └── BpMessageSupport.php
├── Model/                      # Models
│   ├── BpMessageModel.php
│   ├── BpMessageEmailModel.php
│   └── BpMessageEmailTemplateModel.php
├── Service/                    # Services
│   ├── LotManager.php
│   ├── EmailLotManager.php
│   ├── MessageMapper.php
│   ├── EmailMessageMapper.php
│   └── EmailTemplateMessageMapper.php
└── Translations/               # Traduções
    ├── en_US/messages.ini
    └── pt_BR/messages.ini

```

### Padrões de Código

[](#padrões-de-código)

#### 1. SQL Fallback Pattern

[](#1-sql-fallback-pattern)

Use este padrão para operações críticas:

```
// EntityManager
$entity->setField($value);
$this->entityManager->flush();

// SQL Fallback
$connection = $this->entityManager->getConnection();
$connection->executeStatement(
    'UPDATE table SET field = ? WHERE id = ?',
    [$value, $entity->getId()]
);

// Refresh
$this->entityManager->refresh($entity);
```

#### 2. Unicidade de Lotes

[](#2-unicidade-de-lotes)

Ao buscar ou criar lotes, sempre verifique:

```
// Para message lots
$qb->where('l.campaignId = :campaignId')
    ->andWhere('l.idQuotaSettings = :idQuotaSettings')
    ->andWhere('l.idServiceSettings = :idServiceSettings')
    ->andWhere('l.serviceType = :serviceType');

// Para email lots
$qb->where('l.campaignId = :campaignId')
    ->andWhere('l.idQuotaSettings = 0')
    ->andWhere('l.idServiceSettings = :idServiceSettings');
```

#### 3. Processamento Separado

[](#3-processamento-separado)

Message lots e email lots são processados separadamente:

```
// BpMessageModel
->andWhere('l.idQuotaSettings > 0')  // Message lots

// BpMessageEmailModel
->andWhere('l.idQuotaSettings = 0')  // Email lots
```

### Adicionar Nova Ação de Campanha

[](#adicionar-nova-ação-de-campanha)

1. Criar Form Type em `Form/Type/`:

```
class NewActionType extends AbstractType { ... }
```

2. Criar Model em `Model/`:

```
class NewModel {
    public function sendNewType(Lead $lead, array $config, Campaign $campaign): array
}
```

3. Registrar no `CampaignSubscriber.php`:

```
CampaignEvents::CAMPAIGN_ON_BUILD => [
    ['onCampaignBuild', 0],
],
```

4. Adicionar traduções em `Translations/*/messages.ini`
5. Registrar serviços em `Config/config.php`

### Testes

[](#testes)

```
# Criar template de teste
php bin/console mautic:bpmessage:create-test-template

# Testar ações
php bin/console mautic:bpmessage:test-actions --contacts=10 --action=message

# Ver logs
tail -f var/logs/mautic_dev.log | grep BpMessage
```

### Debug

[](#debug)

Ativar logs detalhados:

```
# Ver requests HTTP
tail -f var/logs/mautic_dev.log | grep "BpMessage HTTP"

# Ver operações de lote
tail -f var/logs/mautic_dev.log | grep "BpMessage.*lot"

# Ver processamento
tail -f var/logs/mautic_dev.log | grep "Processing"
```

📄 Licença
---------

[](#-licença)

GPL-3.0-or-later

👥 Autores
---------

[](#-autores)

**Bellinati Perez**

🤝 Contribuindo
--------------

[](#-contribuindo)

Contribuições são bem-vindas! Por favor:

1. Fork o projeto
2. Crie uma branch para sua feature (`git checkout -b feature/AmazingFeature`)
3. Commit suas mudanças (`git commit -m 'Add some AmazingFeature'`)
4. Push para a branch (`git push origin feature/AmazingFeature`)
5. Abra um Pull Request

📞 Suporte
---------

[](#-suporte)

Para suporte, abra uma issue no repositório.

---

📝 Changelog
-----------

[](#-changelog)

### v2.0.0 (2025-01-08)

[](#v200-2025-01-08)

- ✅ Adicionadas 3 ações de campanha (Message, Email, Email Template)
- ✅ Implementado sistema de unicidade de lotes
- ✅ Adicionado SQL fallback pattern para garantir persistência
- ✅ Implementado --force-close para processamento imediato
- ✅ Separado processamento de message lots e email lots
- ✅ Corrigida persistência do finishLot()
- ✅ Adicionado campo service\_type para unicidade
- ✅ Melhorias nos logs e debugging
- ✅ Comandos de teste e validação

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance82

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community5

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

44

Last Release

94d ago

Major Versions

0.0.29 → 5.2.x-dev2025-12-31

### Community

Maintainers

![](https://www.gravatar.com/avatar/c4970fb958f38eb5b7bef9a60c2cba0758aa2c5c3e597f1a71d52b411f89d5cb?d=identicon)[bellinatiperez](/maintainers/bellinatiperez)

---

Tags

pluginMauticsmsbatchwhatsapprcsbpmessage

### Embed Badge

![Health badge](/badges/bellinatiperez-bpmessage-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/bellinatiperez-bpmessage-bundle/health.svg)](https://phpackages.com/packages/bellinatiperez-bpmessage-bundle)
```

###  Alternatives

[mageplaza/module-smtp

SMTP Extension for Magento 2 helps the owner of store simply install SMTP (Simple Mail Transfer Protocol) server which transmits the messages into codes or numbers

3015.9M8](/packages/mageplaza-module-smtp)[etailors/mautic-amazon-ses

Amazon SES Mailer Plugin for Mautic

522.0k](/packages/etailors-mautic-amazon-ses)[pabloveintimilla/mautic-amazon-ses

Mautic 5 plugin that provides Amazon SES as an email transport and callback to process bounces

452.4k](/packages/pabloveintimilla-mautic-amazon-ses)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
