Transferência de cliente por organização

TLDR: mover o vínculo de um cliente com organizações específicas para outro cliente, sem unificar os cadastros nem desativar ninguém.

Contexto

Existem situações em que um mesmo comprador ficou dividido em dois cadastros, com emails diferentes. O merge total existente resolve o caso extremo, mas não serve quando o ajuste precisa ser parcial — quando só algumas organizações devem mudar de dono e os dois cadastros precisam continuar existindo.

Caso real que motivou a mudança:

  • Cliente A (cadastro principal) está em ibft.
  • Cliente B (mesma pessoa, com outro email) está em onion e citrg.
  • Queremos trazer citrg para o Cliente A e manter onion no Cliente B.
  • Resultado esperado: Cliente A fica com ibft e citrg; Cliente B permanece com onion.

Objetivos

  • Permitir uma transferência por organização, não um merge completo.
  • Exigir do operador o email de origem, o email de destino e as organizações a transferir.
  • Oferecer para seleção apenas organizações que realmente pertencem ao cliente de origem.
  • Manter os dois clientes ativos após a transferência.
  • Limitar o impacto ao escopo selecionado — vínculos e pagamentos das organizações escolhidas.
  • Atualizar o Asaas apenas para as organizações selecionadas.
  • Registrar a operação em log para auditoria.

Fora de escopo

  • Desativar o cliente de origem.
  • Alterar email de qualquer cliente.
  • Executar sincronização global para sistemas externos.
  • Atualizar o Asaas fora do conjunto de organizações escolhido.
  • Processar todas as organizações de uma vez.

Mudanças

Fluxo principal

  1. O operador abre a opção “Transferir por organização”.
  2. Informa o email do cliente que vai ceder as organizações (origem).
  3. Informa o email do cliente que vai receber as organizações (destino).
  4. O sistema mostra somente as organizações que podem ser transferidas.
  5. O operador escolhe quais organizações mover.
  6. Antes de finalizar, o sistema mostra um resumo do que vai mudar.
  7. O operador confirma.
  8. O sistema realiza a transferência e mostra a confirmação.
  9. O sistema atualiza o Asaas apenas nas organizações selecionadas.
  10. O histórico da ação fica salvo para consulta futura.

Exceções e tratamento esperado

# Situação Causa Tratamento
1 Email de origem não encontrado Não existe cliente com o email informado Bloquear a ação e orientar o operador a revisar o email
2 Email de destino não encontrado Não existe cliente de destino com o email informado Bloquear a ação e orientar correção
3 Origem e destino são o mesmo cliente Operador informou o mesmo email, ou clientes equivalentes Bloquear a ação com mensagem clara
4 Nenhuma organização elegível Cliente de origem não tem vínculo nas organizações desejadas Impedir a confirmação e informar que não há itens para transferir
5 Organização inválida selecionada Tentativa de transferir organização que não pertence à origem Bloquear a operação por segurança
6 Conflito no destino Cliente de destino já tem vínculo que conflita com o transferido Aplicar a regra definida — bloquear com mensagem clara ou tratar como idempotente
7 Duas transferências simultâneas para a mesma origem Concorrência operacional Proteger a execução para garantir consistência e evitar duplicidade
8 Falha inesperada durante a execução Erro interno ou indisponibilidade temporária Falhar com segurança, sem resultado parcial inconsistente, e registrar log
9 Falha ao atualizar o Asaas no escopo Indisponibilidade ou erro de comunicação com o Asaas Exibir mensagem para nova tentativa controlada e registrar em detalhe no histórico

Como verificar

  1. Criar dois clientes com vínculos em organizações diferentes e transferir apenas uma organização — confirmar que apenas os OrganizationCustomer e Payment daquela organização mudaram de dono.
  2. Confirmar que ambos os clientes continuam com active = true e com os emails originais.
  3. Confirmar que o IbftEmailSyncJob não é acionado neste fluxo.
  4. Rodar a mesma transferência duas vezes e confirmar que não há duplicação de vínculo.
  5. Conferir o registro de auditoria em WebhookLog com o event_type da transferência.

Documentação