Fluxos - Transferir Passageiro entre Excursões
O que é
A transferência de passageiro é um fluxo cross-módulo que toca cadastro de passageiros, reservas (Order) e financeiro numa única transação. Em vez de cancelar a reserva atual e recadastrar o cliente noutra excursão (perdendo histórico e exigindo reconciliação manual do dinheiro já pago), a transferência preserva o vínculo cliente-empresa, gera um novo ExcursaoPassageiro na excursão destino, transporta o crédito pago automaticamente e cria um log de auditoria (TransferenciaExcursaoLog) com o snapshot completo do estado anterior.
O operador normalmente chega a este fluxo quando o cliente desistiu da data original mas quer viajar com a empresa em outra excursão, quando a empresa reagrupa duas excursões com baixa procura ou quando há remarcação por motivo de força maior (clima, sinistro, alteração de roteiro).
Quando transferir vs. cancelar e recriar
| Situação | Caminho recomendado |
|---|---|
| Cliente quer trocar de data e empresa quer manter o pagamento já feito | Transferir |
| Cliente quer reembolso em dinheiro ou estorno no cartão | Cancelar (ver fluxo de cancelar com pagamento) |
| Mudança apenas de transporte/embarque na mesma excursão | Usar a ação Trocar Transporte na linha do passageiro, não transferência |
| Passageiro já fez check-in | Reverter o check-in no app do guia antes; transferir é bloqueado |
| Empresa quer juntar duas excursões com poucos pax | Transferir em lote (uma por vez) e depois despublicar a origem |
| Cliente tem 2 reservas na mesma data e quer fundir | Cancelar a duplicata - a transferência bloqueia se já existir o cliente no destino |
A regra de bolso é: se o objetivo final é manter o cliente na empresa em outra excursão, transferir poupa retrabalho (não precisa reemitir contrato manual, não precisa pedir os dados do cliente de novo, o crédito é aplicado automaticamente). Se o objetivo é devolver dinheiro, cancelar é o caminho - a transferência não estorna pagamentos no meio de pagamento.
Como usar (modal de 3 passos)
- Vá em Viagens (Excursões) no menu lateral e abra a excursão de origem.
- Acesse a aba Passageiros.
- Na linha do passageiro, abra o dropdown de ações (ícone três pontos) e clique em Transferir p/ outra Excursão.
Passo 1 - Escolher a excursão destino
O modal abre listando todas as excursões com status = publicada e data_inicio >= hoje, exceto a atual. Use o campo de busca para filtrar por nome ou por data (formato dd/mm/yyyy). Clique no card da excursão desejada para avançar.
Passo 2 - Configurar destino e comparar preço
O sistema mostra um comparativo DE / PARA com os dados da origem (transporte, embarque, categoria, assento, valor cobrado, valor pago) à esquerda e os campos editáveis do destino à direita:
- Transporte - oculto se a excursão destino for
pacote_viagemou não tiver transportes; o seletor mostra vagas disponíveis em tempo real. - Embarque - oculto se a excursão destino não tiver embarques cadastrados.
- Categoria - obrigatório; o sistema tenta auto-selecionar a categoria de mesmo nome da origem (ex.: "Adulto" continua "Adulto" no destino).
- Valor a cobrar (R$) - recalculado automaticamente pelo endpoint
transferirPrecoa cada alteração nos dropdowns, mas editável manualmente caso o operador queira aplicar desconto ou cortesia. - Transferir N dependente(s) junto - checkbox amarelo, só aparece quando o passageiro é titular do grupo e tem dependentes ativos.
O bloco lateral mostra três linhas-chave: Diferença (positiva se o destino é mais caro), Crédito disponível (o valor já pago na origem) e Pendente a cobrar (quanto o cliente ainda deve depois de aplicar o crédito). Clique em Revisar e Confirmar.
Passo 3 - Motivo e confirmação
Revise o resumo (origem marcada como transferido, nova reserva no destino, contrato invalidado, assento liberado) e preencha o campo Motivo da transferência (obrigatório, até 500 caracteres - fica gravado no log e na observação do novo passageiro). Clique em Confirmar Transferência.
Casos especiais
Diferença de valores: cobrar adicional ou gerar crédito
A regra é direta:
- Destino mais caro (
valor_destino > valor_pago_origem): o crédito disponível é aplicado integralmente no novo financeiro (viaregistrarPagamentocom forma "dinheiro" e origem "manual"), e a diferença vira pendente a cobrar na nova Order. O cliente continua devendo, agora atrelado à nova reserva. - Destino mais barato (
valor_destino < valor_pago_origem): o sistema aplica o crédito até o limite do valor cobrado no destino e converte o excesso em desconto no financeiro do destino (viaaplicarDesconto, com observação "Credito excedente da transferência"). O resultado é que o passageiro fica com saldo zerado no destino - não há devolução automática de dinheiro. Se o cliente quiser o excedente em dinheiro, é preciso lançar a devolução manualmente no módulo financeiro. - Destino com mesmo valor: o crédito cobre exatamente o novo preço e o passageiro fica quitado.
Para grupos (titular + dependentes transferidos juntos), o cálculo é agregado: soma-se o pago de todos os passageiros do grupo na origem e aplica-se sobre o total do grupo no destino. Toda a contabilidade fica concentrada no financeiro do titular.
O que acontece com o assento
O assento da excursão de origem é liberado automaticamente (assento = null) quando o passageiro é marcado como transferido. No passo 2 do modal há um campo opcional Assento para já escolher o novo lugar no destino - se ficar vazio, o passageiro fica sem assento atribuído e o operador pode definir depois pela tela de mapa de assentos da excursão destino. A liberação acontece antes do soft-delete do passageiro origem, então o assento volta a aparecer disponível no mapa imediatamente.
Histórico financeiro: segue ou recomeça?
O histórico financeiro recomeça no destino, mas o rastro fica preservado na origem para auditoria. Especificamente:
- O
ExcursaoPassageiroFinanceiroda origem é marcado comostatus = canceladocom observação "Transferido para excursão: {destino}". Os pagamentos antigos continuam visíveis na consulta do passageiro origem (que fica soft-deleted, acessível via histórico). - O novo
ExcursaoPassageiroFinanceirono destino começa comvalor_pago = 0e recebe um único lançamento de crédito de valor igual ao pago na origem, identificado como "Credito transferido da excursão: {origem} (Reserva #{código})". - Um registro espelho é inserido em
order_paymentsda nova Order, para manter coerência com relatórios de receita (dashboard de GMV, ticket médio). - O log
TransferenciaExcursaoLogguarda o snapshot completo do estado anterior (estado_antes) e os valores de origem, destino e diferença - usado para qualquer reconciliação posterior.
Resultado prático: o relatório financeiro do passageiro no destino mostra apenas o crédito transferido como entrada, não os pagamentos individuais antigos. Para ver o histórico completo, é preciso consultar a reserva origem (Order soft-deletada) ou o log de transferência.
Passageiro com check-in já feito
Bloqueado pelo controller. Se o passageiro tem registro em ExcursaoCheckin (fezCheckin() retorna true), o endpoint devolve "Não e possível transferir um passageiro que ja fez check-in" e o botão Transferir p/ outra Excursão sequer aparece no dropdown. Para destravar, o guia precisa reverter o check-in no app do guia (ou um admin precisa apagar o registro de check-in diretamente). Faz sentido: depois do embarque o passageiro já consumiu o serviço daquela excursão.
Pagamento via meio de pagamento (Mercado Pago, Asaas, Pagar.me, InfinitePay)
A transferência não interage com o meio de pagamento. O valor pago no cartão/PIX/boleto continua creditado para a empresa, e o sistema apenas o realoca para a nova reserva como crédito interno. Isso significa que:
- Não há estorno automático no cartão.
- Se o destino for mais barato e gerar excedente, o cliente não recebe devolução automática - o excedente vira desconto no novo financeiro (saldo a favor que zera a próxima cobrança, mas não vira dinheiro de volta na conta dele).
- Se o cliente exigir reembolso ao meio de pagamento (chargeback, PIX devolvido), o caminho correto é cancelar a reserva original e processar o estorno manualmente no painel do meio de pagamento - depois recadastrar no destino se o cliente ainda quiser viajar.
Dependentes: transferir o grupo todo de uma vez
Quando o passageiro é titular do grupo (tem dependentes ativos com o mesmo comprador_id), aparece o checkbox Transferir N dependente(s) junto no passo 2. Marcado, todos os dependentes ativos do grupo são movidos na mesma transação SQL, reaproveitando a mesma Order do titular no destino (não cria Order por dependente - esse era um bug histórico). Categoria de cada dependente é preservada pelo nome ("Criança" continua "Criança") quando o destino tem categoria equivalente.
Cliente já cadastrado na excursão destino
Antes de executar, o sistema verifica se o cliente_id do passageiro já existe na excursão de destino com status diferente de cancelado/transferido. Se existir, devolve "Este cliente ja esta cadastrado na excursão de destino" e aborta - para evitar duplicar o cliente na mesma viagem. Nesse caso é preciso decidir manualmente qual reserva manter.
Lista de espera e contrato
Ao concluir a transferência, dois efeitos colaterais acontecem:
- A lista de espera da excursão origem é processada (via job
ProcessarListaEsperaagendado para 10 segundos depois) - alguém da fila pode ser convertido automaticamente, já que uma vaga liberou. - O contrato do grupo do comprador na origem é invalidado (via
ContratoService::invalidarAceiteGrupo). Todos os passageiros que tinham assinado o mesmo contrato precisam reassinar. No destino, o sistema não cria automaticamente um novo contrato - o operador deve emitir/coletar o aceite seguindo o fluxo normal de contratos.
Erros comuns e como resolver
- "Este passageiro não pode ser transferido" - Causa: status fora de
confirmado/pendente(já cancelado, transferido, no-show). Solução: rever o status; reservas canceladas exigem recadastro, não transferência. - "Não e possível transferir um passageiro que ja fez check-in" - Causa: existe registro em
ExcursaoCheckin. Solução: reverter o check-in no app do guia antes de transferir. - "Este cliente ja esta cadastrado na excursão de destino" - Causa: existe outro passageiro ativo do mesmo cliente na excursão escolhida. Solução: cancelar a duplicata no destino ou escolher outra excursão.
- "O veículo '{nome}' no destino está lotado - escolha outro transporte ou aguarde liberar vaga." - Causa: capacidade do
excursao_transporteselecionado se esgotou entre o preview e o execute. Solução: voltar ao passo 2 e selecionar outro transporte ou desmarcar a seleção (quando o destino aceita passageiro sem transporte). - "Este passageiro ja foi transferido. Recarregue a página." - Causa: duplo-clique no botão Confirmar - a segunda chamada perde o lock pessimista e detecta o estado já transferido. Solução: recarregar; a primeira chamada concluiu.
- "A excursão de destino não esta publicada" - Causa: a excursão destino foi despublicada entre o preview e o execute. Solução: voltar ao passo 1 e escolher outra excursão publicada.
- "Passageiro não pertence a esta excursão" - Causa:
excursao_idda rota não bate com o do passageiro (URL adulterada ou cache antigo). Solução: recarregar a página e iniciar o fluxo pelo dropdown novamente.
Onde encontrar
- URL:
/admin/excursoes/{excursao}/passageiros - Endpoint Listar destinos:
GET /admin/api/excursoes/{excursao}/passageiros/{passageiro}/transferir-excursao/excursoes - Endpoint Preview:
GET /admin/api/excursoes/{excursao}/passageiros/{passageiro}/transferir-excursao/preview - Endpoint Preço no destino:
GET /admin/api/excursoes/{excursao}/passageiros/{passageiro}/transferir-excursao/preco - Endpoint Executar:
POST /admin/api/excursoes/{excursao}/passageiros/{passageiro}/transferir-excursao - Caminho no menu: Viagens (Excursões) > {excursão} > Passageiros > dropdown da linha do passageiro
- Permissões necessárias: ver as viagens para listar e editar as viagens para executar
- Módulo necessário: nenhum (parte do core); a sincronia com contas a receber acontece automaticamente quando o módulo Gestão Financeira está ativo
Veja também
Passageiros - Cancelar e Transferir- detalhe da ação no menu da linha do passageiro e regras de cancelamento.- Fluxos - Cancelar Reserva com Pagamento - caminho alternativo quando o cliente quer dinheiro de volta em vez de remarcar.