Skip to content

REF-901-01: HubSpot Sync Rules

ADR: ADR-901 — IntegrationsEscopo: Dual-account, source of truth por campo, lead dedup, isolamento de deals, sync bidirecional de quotes, conflito de campo, 7 serviços migrados


1. Dual-Account

MIDDAG opera dois HubSpots: BR e Global. Mesmo lead/empresa pode existir em ambos.

AspectoHubSpot BRHubSpot Global
MercadoBrasilInternacional
MoedaBRLUSD
DealsDeals BRDeals LLC
Sync comOrgs billing_entity=brOrgs billing_entity=global

2. Source of Truth por Campo

DadoSource of TruthDireçãoRegra de Conflito
Campos da OrganizationPluginPlugin → HubSpotPlugin vence. Audit trail em conflito.
Deals / PipelineHubSpotHubSpot → PluginHubSpot vence. Plugin lê, não escreve.
Status do QuotePluginPlugin → HubSpotPlugin vence (lifecycle do quote).
Dados do Quote (criação)HubSpotHubSpot → PluginHubSpot inicia, plugin armazena.

Regra: Sync por campo, não por entidade inteira. Nunca sobrescrever entidade completa.


3. Lead Dedup

Organization no plugin tem dois campos:

CampoValorDescrição
hubspot_company_id_brCompany ID BRVincula company no HubSpot BR
hubspot_company_id_globalCompany ID LLCVincula company no HubSpot Global

Mesmo cliente pode estar nos dois HubSpots — vinculado via Organization. Plugin é ponto de dedup.


4. Isolamento de Deals

RegraDetalhe
Deals BR → só HubSpot BRSem cross-sync entre contas
Deals Global → só HubSpot GlobalCada conta tem deals independentes
Plugin lê deals de ambosExibir no admin UI (somente leitura)
Plugin NÃO cria dealsDeals criados no HubSpot por vendas

5. Sync Bidirecional de Quotes

Criação (HubSpot → Plugin):
  Deal avança para stage de quote
    → Webhook: deal updated
    → Plugin cria Quote (status: draft) com dados do deal
    → Quote armazena hubspot_deal_id

Status (Plugin → HubSpot):
  Cliente aceita quote no portal
    → Plugin: status → accepted
    → Sync: atualiza propriedade do deal no HubSpot

  Quote pago:
    → Plugin: status → paid
    → Sync: deal stage atualizado no HubSpot

Cada quote pertence a uma entidade (BR ou Global) — sync vai para HubSpot correto.


6. Conflito de Campo

CenárioResolução
Campo editado no HubSpot E no pluginPlugin vence (mestre para org data)
Editado apenas no HubSpotPlugin aceita (próximo sync)
Editado apenas no pluginPush para HubSpot
Conflito detectadoAudit trail: campo, valor antigo, valor novo, fonte que venceu

7. Serviços HubSpot Migrados do Theme

#ServiçoFunção
1CompanyServiceSync Organization ↔ HubSpot Company
2ContactServiceSync Collaborator → HubSpot Contact
3DealServiceLeitura de deals HubSpot → exibição admin
4QuoteServiceSync bidirecional de quotes
5AssociationServiceVinculação company↔contact↔deal
6SearchServiceBusca de empresas/contatos no HubSpot
7LineItemServiceSync de line items de quote

Todos migrados do theme. Roteamento dual-account adicionado na v5.0.


8. Webhook Events e Handler

O HubSpot envia webhooks para eventos de deals, quotes e contacts. Endpoints separados por conta:

URLConta
/wp-json/middag-account/v1/webhooks/hubspot/brHubSpot BR
/wp-json/middag-account/v1/webhooks/hubspot/llcHubSpot LLC

8.1 Eventos Tratados

Deals:

EventoAção no Plugin
deal.creationRegistra oportunidade localmente
deal.propertyChange (stage)Atualiza stage/amount/closedate locais
deal.deletionMarca deal como removido

Quotes:

EventoAção no Plugin
quote.creationCria Quote no plugin (status: draft)
quote.propertyChangeAtualiza Quote local
quote.deletionMarca Quote como cancelado

Contacts:

EventoAção no Plugin
contact.creationCria/atualiza contato vinculado à Organization
contact.propertyChangeAtualiza dados de contato
contact.deletionDesativa contato

8.2 Requisitos do Handler

Cada webhook handler implementa:

RequisitoDetalhe
Validação de assinaturaHMAC com secret configurado por conta
IdempotênciaVia event_id — skip se já processado
Retry com backoffBackoff exponencial para falhas de processamento
Logging estruturadoTimestamp, direção, hash do payload, status do resultado
Prevenção de loopsEventos originados pelo plugin não disparam re-sync

9. DTOs HubSpot

O namespace Middag\Account\Integration\HubSpot\Models\ contém DTOs para cada entidade:

DTOCampos Adicionais v5.0
ContactCampos de organização e papel (role) do colaborador
CompanyCampos de dual-account (billing_entity) e vinculação com Organization
DealCampos de stage mapping e probabilidade
LineItemMantido (já completo da migração v3)
QuoteCampos de status do ciclo de vida (draft/sent/accepted/paid)
WebhookEventRepresentação padronizada de eventos recebidos (novo)
SyncStatusRastreamento de estado de sincronização por entidade (novo)

10. Namespace e Estrutura

Middag\Account\
  Integration\
    HubSpot\
      HubSpotClient.php             — cliente API dual-account (forCompany pattern)
      HubSpotWebhookHandler.php     — processamento de eventos de webhook
      HubSpotSyncService.php        — sincronização Plugin → HubSpot
      Models\
        Contact.php
        Company.php
        Deal.php
        LineItem.php
        Quote.php
        WebhookEvent.php
        SyncStatus.php

  Api\
    Webhook\
      HubSpotWebhookController.php  — endpoint REST que recebe webhooks

O controller vive em Api\Webhook\ (conforme ADR-103). A lógica de processamento permanece em Integration\HubSpot\HubSpotWebhookHandler.


11. Configuração Dual-Account

Env VarDescrição
HUBSPOT_BR_ACCESS_TOKENAccess token HubSpot BR
HUBSPOT_BR_PORTAL_IDPortal ID HubSpot BR
HUBSPOT_LLC_ACCESS_TOKENAccess token HubSpot LLC
HUBSPOT_LLC_PORTAL_IDPortal ID HubSpot LLC

O HubSpotClient segue o mesmo padrão do StripeClientforCompany($billingEntity) retorna client configurado com credenciais da conta correspondente.


12. Sync Bidirecional Completa

12.1 Direção de Sincronização por Dado

DadoDireçãoDetalhe
Deals (pipeline, stage, valor)HubSpot → PluginSales team gerencia no HubSpot
Quotes (criação, edição)HubSpot → PluginSales team cria no HubSpot
Quote status (aceito, rejeitado)Plugin → HubSpotCliente age no portal
Order/payment statusPlugin → HubSpotWooCommerce confirma pagamento
Contact (dados comerciais)HubSpot → PluginCRM é fonte de contatos
Organization (verificação)Plugin → HubSpotPlugin gerencia verificação
Ticket (suporte)BidirecionalCriado no portal, gerenciado no CRM

12.2 Organization vinculada a HubSpot Company IDs

Organization mantém vinculação com ambas as contas:

CampoDescrição
hubspot_company_id_brCompany ID no CRM MIDDAG BR
hubspot_company_id_globalCompany ID no CRM MIDDAG LLC

Criação de Organization no plugin pode disparar criação de Company no HubSpot (e vice-versa via webhook). O CompanyService sincroniza dados entre Organization e as Companies correspondentes.