Pular para conteúdo

Regras de Negócio

🎯 Propósito: este é o documento de consulta do suporte interno. Reúne as regras que governam o sistema "por baixo dos panos" — justamente as que a gente esquece em features pouco usadas. Quando alguém perguntar "por que o sistema fez X?", a resposta provavelmente está aqui.


1. Pessoas, Usuários e Perfis de acesso

  • Usuário ≠ Pessoa. Usuário faz login (e-mail/senha); Pessoa salta/trabalha e tem carteira. Um usuário pode estar ligado a uma pessoa, mas não precisa.
  • Perfil de acesso ≠ classificação da pessoa. Os perfis de acesso (o que o usuário pode fazer) são um conjunto fechado: Administrador, Operacional, Financeiro, Staff de campo, Dobrador, Atleta. A classificação operacional da pessoa (instrutor, piloto, tandem, videomaker, rigger…) vive nas flags da Pessoa, derivadas de licença, e serve para filtrar/escalar — não dá acesso. Acesso é validado por capability (ação): GET exige *.view, alteração exige *.manage/ação específica. O mapa role→capability é editável pelo system admin em /system/rbac (vale para todas as DZs); o código é o seed + fallback, e o perfil Administrador sempre tem tudo (não dá para se trancar fora).
  • Modo "somente leitura" automático nas telas. Quando o usuário tem o *.view mas não o *.manage de uma área (ex.: financial em Locais, ou staff no Manifesto), a UI esconde/desabilita as ações de gerência: o manifesto entra em modo travado (sem arrastar, sem check-in), Reservas esconde criar/editar/sync, Pessoas esconde criar/editar/convite/excluir, Configurações da DZ desabilita o form e mostra um selo "Somente leitura", e cada catálogo esconde criar/editar/excluir. Assim o usuário não recebe 403 ao clicar em algo que o perfil não pode.
  • Comparador de perfis na tela de Equipe. Ao convidar/editar um membro, o ícone ao lado de "Funções" abre um diálogo com a matriz role × área (Gerencia/Visualiza/Aprova) — é a fonte rápida pro admin entender o que vai conceder.
  • Adicionar um Dobrador cria/vincula uma Pessoa automaticamente e marca a flag é_dobrador. Os demais perfis de acesso não marcam flags — a classificação vem das licenças.
  • Só Administrador concede o perfil Administrador. Operacional gerencia a equipe (criar/editar/resetar senha) mas não pode atribuir/alterar/remover o perfil Administrador (sem autopromoção).
  • As funções da Pessoa são derivadas das licenças, não marcadas à mão. é_atleta, é_instrutor, é_rigger, é_piloto, é_rta são atualizadas automaticamente quando a licença/habilitação muda:
  • é_atleta ← licença de salto válida (A/B/C/D/AI)
  • é_instrutor ← habilitação real de instrutor válida. No cadastro via CBPq, só contam habilitações de instrutor de verdade: Instrutor AFF/ASL, Treinador BBF, Piloto Tandem, Examinador. A habilitação "Aluno em Instrução" e o "CIS" genérico (que o CBPq joga na mesma categoria CIS) não marcam a pessoa como instrutor.
  • é_rigger ← certificação de dobra de reserva
  • é_piloto ← habilitação de piloto válida (PP/PC/PLA)
  • é_default_rta: no máximo uma pessoa por DZ pode ser o RTA padrão (auto-selecionado ao criar decolagem).

Validações no cadastro/edição de Pessoa

  • E-mail obrigatório. Toda Pessoa precisa de e-mail; o sistema rejeita criação sem ele.
  • E-mail único por DZ. Não dá pra criar duas Pessoas com o mesmo e-mail no mesmo tenant (constraint unique_people_email_per_tenant). Conflito retorna 409.
  • Documento único por DZ. Mesmo CPF/Passaporte não pode aparecer em duas Pessoas (unique_person_document por tenant_id + tipo + número).
  • CPF é validado. Quando o tipo de documento é CPF, o número passa por validação de dígitos verificadores. Acentos/máscara são strip-ados — armazenamos só dígitos.
  • Tipos de documento aceitos: apenas CPF e Passaporte. Pessoas legadas com RG/CNH continuam funcionando, mas não dá pra cadastrar novos.
  • Deduplicação proativa por nome+nascimento. No fluxo de criação manual, antes de gravar o sistema busca Pessoas com mesmo nome (normalizado) e data de nascimento compatível; se houver candidatos, abre um diálogo de confirmação. O fluxo de lookup CBPq já tem dedup próprio por nome.
  • Normalização automática. Nome e apelido entram com trim + colapso de espaços; e-mail entra em lowercase. Evita duplicatas por digitação inconsistente.

2. Acesso aos Portais

  • Portal do atleta tem dois interruptores em série: o da DZ (portal_enabled) e o da pessoa (portal_access_enabled). Ambos precisam estar ligados.
  • O toggle individual da pessoa (portal_access_enabled) é o que efetivamente dirige o papel de atleta + auto-cadastro/OAuth/vínculo no login. (O antigo toggle por equipe foi removido.)
  • Modo de registro (invite_only vs aberto) decide se o atleta entra só por convite ou por auto-cadastro.
  • Portal do dobrador exige packer_portal_enabled na DZ e a função de dobrador na pessoa.

Acesso temporário (janelas de datas)

  • Cada membro da equipe tem um modo de acesso: permanente (padrão) ou temporário. O temporário só tem acesso nas janelas de acesso cadastradas pela DZ (períodos De/Até, datas inclusivas, N por membro, sem sobreposição, data final obrigatória).
  • A regra compara a data da decolagem/manifesto (ou do serviço avulso) com as janelas — nunca o "agora". Assim a dobra da carga do dia 07 pode ser marcada no dia 07, e o fechamento do manifesto continua sendo a trava real. Onde não há carga (preços, catálogo), a referência é hoje na localidade padrão da DZ.
  • Fora da janela o membro continua entrando: vê o próprio histórico, relatórios, carteira, pagamentos e Pix. Perde o que é da DZ: manifesto do dia (no_access), registrar dobra/serviço, confirmar equipamento, valores de dobra da DZ e preços do catálogo (viram --,--) e a edição de Meus preços.
  • Membro temporário nunca cria/edita/desativa/exclui serviços do catálogo, independente da data.
  • O operador também não consegue marcar dobra em nome de um dobrador temporário fora da janela; o seletor de dobradores do manifesto lista só quem tem acesso na data da carga. Dobrador sem vínculo de equipe (só a função na pessoa) nunca é restringido.
  • Modo temporário só é aceito para os perfis Staff de campo, RTA, Dobrador, Atleta, Aeronauta e Abastecedor — nunca Administrador, Operacional ou Financeiro.
  • Voltar para permanente mantém as janelas gravadas (ficam inertes).
  • Fase 2 (não implementada): aplicar a mesma regra ao manifesto do app administrativo para staff/instrutor temporário.

Escolha de portal no login

  • Quando o usuário tem acesso a um único portal (na organização selecionada), o login o leva direto para ele.
  • Com dois ou mais portais, entra em jogo o Portal padrão do usuário (em Meu perfil → Preferências): se houver um portal fixo válido, vai direto; se estiver como "Perguntar sempre" (ou não definido), o AiroDZ mostra a tela de escolha de portal. Na tela, marcar "Entrar sempre por aqui" grava aquele portal como padrão.
  • A preferência é do usuário (vale em todas as organizações). Se o portal preferido não existir na organização atual, cai na regra normal (entra direto se houver só um, ou pergunta).

Duração da sessão (sessão estendida)

  • Usuários exclusivamente de portal — quando todos os seus perfis de acesso (em todas as organizações) estão no conjunto de perfis com sessão estendida (por padrão Dobrador e Atleta) — ganham uma sessão mais longa, para não precisarem redigitar a senha a cada consulta rápida.
  • Qualquer acesso à administração (Administrador, Operacional, Financeiro, Staff, RTA) — ou o perfil Aeronauta — mantém a sessão curta, por segurança. A decisão é reavaliada a cada login e renovação.
  • As durações (sessão padrão × estendida) e quais perfis ganham a sessão estendida são configuráveis pelo administrador do sistema em Sistema → Sessão e login; os valores de ambiente são o padrão inicial.

3. Decolagem (Load) — Máquina de Estados

Transições válidas (qualquer outra é rejeitada):

rascunho   → agendada, cancelada
agendada   → embarque, rascunho, cancelada
embarque   → decolou, agendada, cancelada
decolou    → pousou
pousou     → (final, sem transição)
cancelada  → (final, sem transição)
  • Agendar exige aeronave + piloto licenciado. Sem piloto com habilitação válida, não passa de rascunho.
  • Piloto padrão da aeronave. Cada aeronave pode ter um piloto padrão (opcional; pessoa com é_piloto). O preenchimento é do backend (igual ao RTA padrão), então vale em todos os caminhos de criação: decolagem avulsa, loads placeholder/rascunho intermediários e criação em lote. Regra: ao criar uma decolagem sem piloto informado, usa o piloto padrão da aeronave; ao trocar a aeronave de uma decolagem sem informar piloto no mesmo request, o piloto passa a ser o padrão da nova aeronave. Um piloto informado explicitamente sempre prevalece. O piloto segue obrigatório para agendar e editável a qualquer momento.
  • Não dá pra alocar mais slots que a capacidade da aeronave.
  • pousou é o gatilho da cobrança. Veja seção 5.
  • Decolar recalcula o agendado das próximas. Ao marcar decolou, o sistema recalcula o horário agendado das decolagens seguintes da mesma aeronave a partir do horário real de decolagem: cada uma vira decolou + tempo de voo da aeronave (EstimatedFlightTime, + abastecimento quando a decolagem está marcada com combustível). Só mexe nas decolagens ainda não decoladas (rascunho/agendada/embarque) — as que já decolaram/pousaram mantêm os horários. Editar manualmente o agendado de uma decolagem também propaga para as seguintes da mesma aeronave, do mesmo jeito.
  • RTA obrigatório para decolar/pousar. Se algum produto da decolagem tem item que paga o RTA e nenhum RTA está atribuído, o sistema bloqueia marcar decolou ou pousou — evita pousar uma carga e só depois perceber que o repasse do RTA não foi gerado.
  • Atribuir RTA numa decolagem já pousada re-gera o repasse. Ao corrigir o RTA (ou a aeronave) de uma decolagem que já pousou, a cobrança roda de novo de forma idempotente: cria o repasse do RTA que faltava sem duplicar as cobranças já feitas.
  • Modo de edição permite editar uma decolagem já pousada (exceção controlada).

4. Manifesto

  • Um manifesto por dia + local. GetOrCreate retorna o existente ou cria.
  • Manifesto pode ser fechado e reaberto.
  • Categoria mínima pode ser definida por manifesto (filtra quem pode saltar).
  • Aeronave do dia. Cada manifesto pode ter uma aeronave padrão do dia, independente da aeronave padrão da DZ. Ao criar uma decolagem nova, a aeronave pré-selecionada segue a prioridade: (1) aeronave do dia do manifesto, se definida e ativa; (2) senão, aeronave marcada como padrão da DZ (is_default). É conveniência de UI — só afeta decolagens novas, nunca as já criadas, e a aeronave continua editável. Definir/limpar a aeronave do dia exige manifest.manage e o manifesto aberto.
  • Validação de licença/reserva no manifesto segue o modo configurado na DZ:
  • Estrito → bloqueia.
  • Aviso → alerta e deixa seguir.
  • Não checar (só reserva) → ignora.
  • Licença pendente de validação bloqueia o embarque (espelha o equipamento). Uma licença só é considerada válida para saltos que exigem licença quando está validada pela DZ (ou auto-validada via CBPq), além de estar regular e dentro da validade. Licença pendente de validação cai no modo estrito/aviso acima, com a mensagem específica "licença pendente de validação" (distinta de expirada/inativa).

Retorno a Bordo (embarcou, decolou e voltou sem saltar)

Quando alguém embarca, o avião decola e a pessoa volta sem saltar, marque a vaga como Retorno a Bordo. Por ser uma edição de uma decolagem já pousada, entre no Modo de edição da decolagem e use o botão ⤶ Retorno a Bordo na vaga (abre um diálogo de confirmação, com a opção de já não cobrar). É diferente de No-show (que nem embarcou) e de cancelar a vaga:

  • É uma marca física do salto. O tipo de salto não muda (um tandem continua tandem) — é o que garante que os relatórios saibam a origem.
  • Logbook: aparece com o selo Retorno a Bordo, mas não conta no total de saltos da pessoa.
  • Relatórios: vira categoria própria "Retorno a Bordo" no Relatório RTA e no Operacional-Financeiro (sai das contagens de duplo/aluno/esportivo). A decolagem continua contando.
  • Cobrança (padrão): continua igual. O atleta segue pagando o produto (mesma receita) — útil quando o tandem embarcou e voltou mas é cobrado do mesmo jeito.
  • Não cobrar (opcional): a opção "Não cobrar (Retorno a Bordo)" troca apenas o produto da vaga por um RETORNO A BORDO custo-zero (a DZ cria esse produto/tipo de salto no catálogo). O motor reprocessa a cobrança e estorna o débito; o produto original fica guardado, e desmarcar o Retorno a Bordo restaura o produto e volta a cobrar.

Vaga complementar (pagar mais vagas do que saltadores)

Quando um grupo paga por mais vagas do que as pessoas que sobem — por exemplo, um grupo de gravação que sobe 4 e paga 6 —, as vagas a mais entram como vagas complementares:

  • Pessoa de vaga complementar. No cadastro de Pessoa há a opção "Pessoa de vaga complementar". Uma pessoa marcada assim é apenas um espaço reservado (não é um atleta real) e não exige email. Diferente de qualquer outra pessoa, ela pode ocupar mais de uma vaga na mesma decolagem — não é preciso criar uma pessoa fantasma para cada vaga extra.
  • Como lançar. Crie um tipo de salto para a vaga complementar (classificação Outros) com o produto de vaga, adicione a pessoa de vaga complementar ao grupo quantas vezes precisar e marque as vagas como "pago pelo grupo". O valor é rateado entre os pagantes do grupo e o repasse de vaga do dono do avião conta as vagas normalmente.
  • Relatórios. A vaga complementar aparece como tipo de salto "Outros" e não entra na contagem esportiva (nem no Relatório RTA).

5. Cobrança Automática (Billing) — pousou

Quando a decolagem pousa, ProcessLoadBilling(load, data_do_manifesto) roda nesta ordem:

  1. Filtra slots cobráveis — exclui no_show e cancelada.
  2. Carrega produtos + itens de todos os slots.
  3. Resolve preços versionados pela data do manifesto (não a data de hoje).
  4. Slots sem grupo → débito direto na pessoa.
  5. Para cada grupo:
  6. identifica pagantes (paid_by_group = falso) e pagos (paid_by_group = verdadeiro);
  7. cobra cada pagante pelo próprio produto;
  8. rateia o custo de cada slot pago igualmente entre os pagantes (o último absorve o arredondamento);
  9. comissões add-on: produto próprio do staff → credita o staff (itens performer sem tipo de salto);
  10. comissões de pacote: produto do pagante → credita o staff correspondente (itens performer com tipo de salto → acha o slot de staff daquele tipo);
  11. comissões estáticas: credita o destinatário fixo (static_party, rta, agency, equipment).
  12. roteamento de repasse (org/CNPJ): antes de creditar, o resolver verifica se há uma rota (pessoa, template) definida. Se houver, o crédito vai pra carteira da organização vinculada em vez da conta pessoal — só vale para repasses baseados em pessoa (rta e performer). Ver §6.1.
  13. Repasse de aeronave: depende do modo de repasse da aeronave (payback_mode):
  14. por vaga (padrão): se o produto tem repassa_aeronave, credita o dono o preço de vaga vigente, por vaga paga (override por produto → preço padrão da aeronave);
  15. por decolagem: credita o dono um valor fixo por decolagem (vigente na data do manifesto) quando o load pousa com ≥1 pessoa — independente de assentos e da flag repassa_aeronave. Load vazio não gera repasse. A descrição na carteira mostra Decolagem {ocupados}/{capacidade}.
  16. Faixas por ocupação (por decolagem). O valor por decolagem é o valor normal (avião cheio). Sobre ele a aeronave pode ter faixas "de X até Y pessoas a bordo → R$ Z" (intervalo fechado), versionadas por data em conjunto: aplicar um conjunto encerra o anterior na data e grava o novo numa transação só; o histórico fica por data. Pessoas a bordo = linhas do manifesto com pessoa, sem não compareceu/cancelada (o mesmo X do X/Y; vaga complementar conta; não é a soma de slots_required). Faixas vigentes da mesma aeronave não se sobrepõem (garantido no banco), então no máximo uma cobre a decolagem; fora de qualquer faixa vale o valor normal — buracos são intencionais (ex.: "menos de 8 pessoas paga cheio"). Faixa com "até" acima da capacidade é rejeitada. Alterar o conjunto não mexe em loads já pousados até serem reprocessados (aí o ajuste entra pela diferença). A descrição ganha o sufixo Faixa {X}-{Y} quando uma faixa se aplica. Relatório Repasse de Vagas e Portal do Aeronauta calculam a mesma regra a partir da fonte. Ambos emitem uma única transação aircraft_payback por load (mesmo reference_type), então a reconciliação delta-aware vale igual.
  17. Ajuste de vagas em lote (retroativo). Quando o valor da vaga muda no meio do período (ex.: oscilação do combustível), a DZ pode aplicar o novo valor para vários aviões por vaga de uma vez e reprocessar as carteiras: cada load já pousada com repasse lançado é recalculada e o dono recebe apenas a diferença como ajuste (o histórico é preservado). Regras:
    • Rubricas (um avião por vez): o ajuste edita, de uma vez, a vaga padrão e/ou overrides de produto do avião (tabela de rubricas). O delta de cada rubrica considera só as vagas que a usam; o override de um produto tem precedência sobre a vaga padrão para aquele produto.
    • Período: "a partir de uma data" (aberto, permanente) ou um intervalo de/até — nesse caso os valores novos são temporários e revertem aos anteriores depois do "até" (oscilação passageira).
    • Normalização de vigências: o ajuste faz "cirurgia de intervalo" na linha do tempo de preços — define o valor na janela [de, até], corta/divide as vigências existentes nas bordas e preserva o que havia antes e depois. Funciona para qualquer janela, inclusive no passado ou fora de ordem (não depende de a data ser posterior à última mudança), trata override de produto que só existe parte do período, mescla faixas adjacentes iguais e nunca gera vigência inválida (fim < início).
    • Prévia: mostra, por dono, quantas loads/vagas e o delta em R$, e um detalhe por decolagem agrupado por data (unitário antigo→novo por rubrica, no estilo do relatório repasse-vagas) antes de confirmar. Nada é gravado na prévia. Cada load é reprocessada uma vez ao aplicar, mesmo com várias rubricas.
    • Escopo: só aviões por vaga (os por decolagem ficam de fora) e só corrige loads que já tinham repasse (não faz backfill).
    • Lançamento na carteira: o ajuste entra como uma transação de ajuste (valor = a diferença), aninhada sob o crédito original do payback da load, com descrição autoexplicativa "Reajuste de vaga - Load #N - data - matrícula - " (uma rubrica por tipo de vaga alterado, já que o payback é uma entrada por load).
    • Log: cada aplicação é registrada num histórico (quem, quando, rubricas alteradas, período, delta total, loads reprocessadas) — consultável, sem desfazer (para reverter, roda-se um novo ajuste).
  18. Repasse de equipamento: se o slot tem rig, credita o dono do rig via item de equipamento.

Reconciliação delta-aware (não duplica e corrige)

O motor é delta-aware: a cada reprocesso ele recalcula o valor desejado de cada cobrança e lança só a diferença como ajuste (transações são imutáveis). Buckets: - Cobrança de slot → reference_type = load_billing + slot ID. - Rateio → reference_type = load_billing_split + source_slot_id no metadata. - Comissão → reference_type = load_commission + product_item_id. - Cobrança de complemento → reference_type = load_billing_extra + extra ID.

➡️ Reland / Reprocessar não gera cobrança em dobro (diferença = 0 → nada é criado).

  • Trocar a vaga/produto de um atleta e reprocessar ajusta a conta dele. Se o novo produto é mais barato, gera estorno da diferença; se é mais caro, cobra o complemento. Vale ao editar o produto da vaga numa decolagem já pousada (recálculo imediato) e ao voltar para Agendado e pousar de novo.
  • Estorno automático do que saiu. Vaga/complemento removido, marcado no_show/cancelado, ou atleta trocado de vaga: o motor estorna a cobrança que não vale mais (estorna o antigo, cobra o novo) no próximo reprocesso.
  • Voltar para Agendado não estorna sozinho — a reconciliação acontece quando a decolagem pousa de novo.

Extras (complementos) em grupos

  • Extras pertencem a um slot específico, não ao grupo. Cobrados sempre do slot.person_id, mesmo se o slot estiver marcado paid_by_group.
  • Em tandem completo, os extras digitados no diálogo de alocação ficam no slot do passageiro (leader). Antes desse fix, o fluxo de criação de grupo ignorava silenciosamente o array de extras.
  • No resumo do grupo (mesmo em loads finalizadas) e no detalhamento por produto do dia, os extras aparecem como linhas próprias.

6. Itens de Produto e Templates

  • Sem itens, toda a receita vai pra DZ.
  • Comissão performer COM tipo de salto = modelo pacote (acha o staff pelo tipo de salto no grupo).
  • Comissão performer SEM tipo de salto = modelo add-on (o staff já está no slot do produto).
  • Quando o item está ligado a um Template, o Template manda. Os campos recipient_type / amount / jump_type efetivos vêm do Template (resolva via template, não pelos campos do item). Os campos no item ficam só por compatibilidade com linhas legadas.
  • Modos de cálculo do template: valor fixo, por vaga paga, % da receita.
  • calculation_mode do template é imutável. Depois de criado, o backend rejeita a troca (ErrCalculationModeImmutable, HTTP 400). Pra trocar o modo, crie um novo template. Pra trocar o valor, use o endpoint de preços (/prices) que cria uma nova versão vigente — o valor não é atualizado pelo PUT do template.
  • bills_aircraft só é relevante em produtos jump. Outros tipos (rental/service/merchandise) são forçados a false no save — mesmo se o frontend enviar true.
  • Operador no extra é exigido só quando o produto tem item performer dinâmico. Produtos service sem performer dinâmico (taxa de parcelamento, p.ex.) viram receita pura sem precisar de operador.

Licenças

  • Emissor (CBPq/USPA/ABPq/Outro) é separado de Federação: emissor é a confederação que emite a licença; federação é a associação regional (livre texto). Lookup CBPq seta Emissor = CBPq automaticamente.
  • (tenant_id, license_number) é único em people_license (sem duplicar nº de licença na DZ).
  • (tenant_id, cis_number) também é único.
  • Validação da licença (validation_status: pendingvalidated). Espelha a aprovação de reserva do equipamento. Licença criada/editada pela DZ no admin já nasce validada (a DZ é a autoridade). Licença auto-cadastrada pelo atleta nasce pendente: a CBPq é auto-validada pela integração (quando a DZ deixa "validar licença automaticamente" ligado); USPA/ABPq/Outro ficam pendentes até alguém validar manualmente em Pessoa → Licença → Validar (capability license.validate). Validar registra quem, quando e a fonte (cbpq_auto/manual). Uma licença só vale no manifesto se estiver validada (ver seção Manifesto).

6.1. Roteamento de Repasses (pessoa → org/CNPJ)

Uma pessoa pode acumular vários papéis (RTA, instrutor, câmera) e querer receber cada repasse numa conta diferente — ex.: o pagamento de RTA no CNPJ da empresa dela, mas a comissão de instrutor na conta pessoal. O roteamento resolve isso.

  • Vínculo pessoa↔org. Na edição da pessoa, a seção "Empresas (CNPJ)" vincula a pessoa a organizações. Só vincula Party do tipo ORGANIZATION (party que não é org → 422).
  • Granularidade por template. A chave da rota é (pessoa, template de item). Isso separa câmera de instrutor naturalmente (templates diferentes). Configurado na seção "Roteamento de repasses", com um seletor por template → "Conta pessoal" (padrão) ou uma das empresas vinculadas.
  • Ausência de rota = conta pessoal. Não existe linha "pessoal"; só há registro quando há redirecionamento. O PUT substitui o conjunto inteiro (array vazio = tudo pessoal).
  • Só repasses baseados em pessoa. Roteia rta e performer. Os demais (agency, static_party, equipment, company) já apontam para um party específico — não roteiam. packer é pago no fluxo de confirmação de dobra, fora do template engine.
  • Atribuição preservada. O crédito vai pra carteira da organização, mas a transação grava quem gerou (earned_by_person_id / _name) — relatórios de produção por pessoa continuam corretos. A descrição ganha sufixo "(via Nome)" pra carteira da org mostrar de quem veio.
  • Defina a rota ANTES de cobrar o load. Trocar a rota depois que o load já foi cobrado não move créditos já liquidados (exige reconciliação manual). Não precisa reprocessar nem zerar o billing existente: o motor casa por earner, com fallback legado para transações antigas.
  • RBAC: gerenciar vínculos/rotas usa people.manage (mutação) e people.view (leitura) — é parte de editar a pessoa.
  • Portal: a pessoa vê as carteiras das orgs vinculadas a ela (seção "Minhas empresas"), com guard de posse — só vê a carteira de org à qual está vinculada (não-membro → 403 plano).

7. Preços Versionados

  • Produtos, templates e preço de vaga de aeronave usam intervalos vigente_de / vigente_até (vigente_até = NULL → ativo).
  • A cobrança usa o preço vigente na data do manifesto. Manifesto retroativo cobra o preço da época.
  • O banco impede sobreposição de períodos.
  • Valores de item definidos direto (sem template) NÃO são versionados — são atualizados no lugar. Como o billing roda no mesmo dia, a transação na carteira guarda o valor real como registro histórico.

8. Carteira e Transações

  • Toda Party (pessoa ou organização) tem uma conta por DZ.
  • Transações são imutáveis: nunca são editadas nem apagadas (hooks bloqueiam update/delete). Para corrigir, use ajuste ou estorno (transação relacionada).
  • Cada transação guarda balance_after, referência (load_slot/depósito/ajuste) e metadata — é o registro de auditoria.

9. Dobra (Packer)

  • Dobra só pode ser criada com o manifesto aberto / no mesmo dia.
  • Uma dobra só pode ser desfeita se ainda NÃO foi paga.
  • Origens: auto (motor, ao pousar/decolar), manual_load (reivindicada num slot), manual_independent (avulsa).
  • Status: pendentepago (atleta pagou) / dz_paid (a DZ banca, veio embutido no produto) / waived (cortesia).
  • O gatilho automático (pousou vs decolou) é configurável na DZ (packer_auto_entry_trigger).
  • Dobrador pode ter preço próprio por serviço (override do preço padrão do catálogo).
  • Dobrador com acesso temporário (seção 2): dobra/serviço só na data das suas janelas; catálogo somente leitura; Meus preços só com acesso hoje.
  • Pagamento atleta→dobrador passa por confirmação: pendente_confirmaçãoconfirmado / contestado.
  • Precedência do item de dobra: quando o slot tem complemento de aluguel com item packer, a DZ paga (modelo de aluguel da DZ). O complemento vence sobre qualquer item de dobra no produto principal.
  • Confirmação de dobra sem equipamento no manifesto (tandem). O equipamento é opcional para manifestar, mas o item pode exigir confirmação de dobra. Quando nenhum rig foi marcado no grupo, o Confirmar equipamento aparece na linha do piloto do tandem (a função marcada como quem veste o equipamento atribuído) — não no passageiro. O dobrador escolhe o rig que dobrou e o repasse é gerado ao dono; aluguéis (complementos) confirmam no próprio complemento.
  • Reorganizar decolagem já pousada não perde nem duplica dobras. Ao mover um grupo para outra decolagem, as dobras (e serviços) acompanham a pessoa para o novo slot — sem virar registro "solto" e sem a DZ pagar de novo. Ao remover um slot/pessoa, a dobra pendente ligada é estornada (as já pagas não são tocadas).
  • Gestão pelo operador (manifesto) é recurso base — independe do Portal do Dobrador. O manifesto tem a tela Dobras & equipamentos onde o operador atribui / reatribui / desfaz dobras e confirma / desfaz equipamento, espelhando as ações do portal. Cobre dobras pagas pela DZ (crédito na carteira do dobrador) e pagas pelo atleta (P2P — o atleta acerta direto com o dobrador, sem movimento no ledger), além de aluguel de equipamento. Ciclo de vida: só dá pra reatribuir/desfazer enquanto NÃO estiver pago (status paid trava tudo). Dobra da DZ mexe no ledger (ao reatribuir/desfazer, estorna o dobrador antigo e recredita o novo); dobra do atleta é só troca do registro. Gates por capability: dobra usa manifest.manage, equipamento usa manifest.equipment (sem capability nova). O Portal do Dobrador continua sendo um módulo à parte (autoatendimento do dobrador), gate packer_portal_enabled.

9.1. Repasses de Serviço (Rádio e futuros)

Genéricos pra repasses similares à dobra mas executados por outros profissionais. Hoje cobre rádio AFF; futuros tipos (vídeo, organizador, …) seguem o mesmo padrão.

  • Quem reivindica? Staff de campo (capability radio.claim). No portal do atleta, o staff vê todos os loads do dia e os slots com item de rádio ganham botão "Fiz o rádio".
  • Detecção do item segue a mesma cadeia da dobra: complemento → produto principal → siblings de grupo. Aluguel/complemento de rádio sempre vence.
  • DZ paga. Entry criada com status=dz_paid, vai pra carteira do staff. Atleta NÃO é cobrado por rádio (o repasse é da DZ ao staff).
  • Sem auto-criação ao pousar. Diferente da dobra, nunca cria automaticamente — quem fez o trabalho reivindica via portal. Evita atribuir errado.
  • Janela de undo: enquanto o manifesto estiver aberto, o próprio staff (ou admin) pode desfazer.
  • Conflito de claim: dois staff que clicam quase ao mesmo tempo → o segundo recebe erro de duplicidade (UNIQUE por load_slot_id + service_type). Frontend mostra "já reivindicado por X".
  • Persistência: tabela própria service_entries (não mistura com packer_entries). Permite expandir com video/cameraman sem refactor.

10. Equipamento (Rig) e Reserva

  • Validade da reserva = data da dobra + rig_reserve_pack_expire_months (config da DZ, padrão 6).
  • Re-dobra (repack) deixa a reserva pendente de aprovação → precisa ser aprovada.
  • Validação de reserva vencida no manifesto segue manifest_reserve_validation_mode (estrito/aviso/não checar).
  • A reserva validada é a do equipamento que a pessoa veste. O manifesto checa a reserva do rig atribuído ao slot (o que ela realmente veste) quando há um; só cai no equipamento padrão dela quando não há rig atribuído. No tandem, o rig fica no slot do piloto — então a reserva validada é a do rig de tandem designado, e não a do equipamento esportivo pessoal do piloto (que ele não usa no salto).
  • Flag do tipo de salto wears_assigned_rig ("Veste equipamento designado"). Para papéis que sempre saltam com equipamento designado/da casa (ex.: Tandem Pilot), marque essa flag no tipo de salto. Com ela ligada e sem rig atribuído ao slot, o manifesto não valida o equipamento pessoal da pessoa (apenas libera) — evita o bloqueio falso quando o operador não designou o rig. Com rig atribuído, a reserva dele continua sendo validada normalmente.
  • Equipamento pendente de validação pela DZ (reserva na validade, ainda não aprovada — típico do gear auto-cadastrado pelo atleta) segue uma key separada: manifest_pending_gear_mode (bloquear / alerta / permitir, padrão bloquear). Só tem efeito quando manifest_reserve_validation_mode != não checar. bloquear/alerta disparam o erro error_reserve_pending; em alerta o front oferece "Continuar mesmo assim"; permitir ignora o pendente.
  • Equipamento com dono pessoa (OwnerType=person) precisa ter o PersonID setado para aparecer no perfil da pessoa e em Pessoas → Equipamentos; dono organização/DZ é equipamento da casa.
  • manifest_allow_without_gear decide se dá pra manifestar sem rig vinculado.

Equipamento próprio cadastrado pelo atleta (portal)

  • Pelo portal (Perfil → Meus Equipamentos) o atleta cadastra um equipamento próprio (os cadastrados pela DZ não contam para esse limite). Pode editar o seu, mas não excluir (só a DZ exclui).
  • A categoria é sempre Profissional e o is_rentable é forçado false (não dá pra marcar como alugável pelo portal).
  • O equipamento entra com reserva pendente (ReserveStatus=pending → selo "Pendente de validação pela DZ") e vira o equipamento padrão da pessoa automaticamente.
  • Guard de posse: o atleta só altera/lê o rig que é dele (rig.PersonID == caller → senão 403).

11. Integração Bookeo

  • Mapeie os produtos do Bookeo antes de sincronizar — sem mapeamento, a reserva chega sem produto.
  • A sincronização cria/atualiza reservas e participantes (passageiros viram Pessoas).
  • Importa o depósito pago online.
  • Requer acesso à internet de saída (e o login Google/OIDC também). Em deploy serverless, isso tem implicações de infra — ver CLAUDE.md.

12. Multi-tenant

  • A DZ = Tenant. Todo dado tem tenant_id e é isolado por tenant.
  • As requisições da área administrativa carregam o tenant via header (X-Tenant-ID) e validam o acesso do usuário àquele tenant.

13. Cadastro Público de Atletas

Página pública por DZ (/r/{slug}) onde atletas se cadastram sozinhos. Opt-in — a DZ habilita em Configurações → Dropzone → Portal. Detalhes operacionais em Cadastro Público de Atletas.

Máquina de estados da verificação

Toda Pessoa tem verification_status com 3 valores:

verified              → criada pela DZ ou aprovada após cadastro público (default)
pending_verification  → veio do cadastro público, aguarda DZ revisar
rejected              → DZ rejeitou (motivo registrado, atleta não pode re-tentar)

Transições válidas:

  • DZ-created → verified (sempre, default)
  • Cadastro público + CBPq encontrado → verified
  • Cadastro público + CBPq não encontrado / USPA / ABPq / Outro → pending_verification
  • pending_verificationverified (DZ clicou Verificar)
  • pending_verificationrejected (DZ clicou Rejeitar com motivo)
  • rejected é terminal — não volta nem é retentável pelo formulário

O verification_status é apenas uma etiqueta de revisão da Pessoa — não controla acesso ao portal (que é sempre imediato) nem embarque (que é controlado pela validação da licença). Ver seção Licenças.

Match (bloqueio de duplicata)

A página pública não atualiza Person existente — bloqueia. As chaves de match:

  1. email (case-insensitive)
  2. cpf (sem máscara)
  3. passport_number
  4. name + birth_date (nome case-insensitive, data exata)

Match contra Persons em qualquer status (verified, pending_verification, rejected). Rejeitado bloqueia — força o atleta a contatar a DZ.

Integração CBPq

Se o license_issuer = "CBPq" e license_number preenchido, o backend faz lookup server-side durante o submit (não no cliente — sem endpoint público de lookup, evita virar proxy de scraping). Resultados:

  • validated → snapshot completo salvo em cbpq_lookup_snapshot (JSONB); o cbpqSyncService.Sync() popula licença + endorsements + histórico localmente. Com "validar licença automaticamente" ligado (padrão), a licença CBPq já entra validada (validation_source = cbpq_auto). Licença CBPq irregular/vencida é registrada mas continua bloqueada no manifesto (status/validade reprovam, mesmo validada).
  • not_found ou unavailable → licença fica pendente de validação (DZ valida manualmente); nunca bloqueia o envio.

Conta de portal

A conta no Portal do Atleta é sempre criada na submissão (a DZ escolheu oferecer o cadastro público, então o atleta ganha acesso imediato — CBPq ou não). O User é criado, vinculado com o perfil Atleta, portal_access_enabled = true, e o email de setup-password é enviado (login Google também resolve). O acesso ao portal é independente da validação da licença — o atleta entra e usa o portal; o que fica bloqueado até a licença ser validada é o embarque no manifesto. Se o provisionamento da conta falhar, o cadastro retorna erro (não finge sucesso) e a Pessoa pendente fica recuperável pela ação Verificar.

Anti-fraude

  • reCAPTCHA v3 com threshold ≥ 0.5
  • Rate limit 5 submissões/hora por IP (tabela public_registration_attempts)
  • Audit: self_registered_at, self_registered_ip, self_registered_user_agent gravados na Person

14. Relatório RTA (Atividades Realizadas)

Relatório em Relatórios para o comitê de segurança da CBPq. Conta, por mês (ou período escolhido), 1 por vaga saltada (load decolou/pousou; exclui vagas não compareceu/canceladas):

  • Decolagens = nº de voos.
  • Total de saltos (vagas totais) = duplos + alunos + esportivos (só saltos).
  • Duplos = só o passageiro do tandem (classificação tandem). Detalhado por tipo de salto.
  • Alunos = classificação student (BBF/AFF). Detalhado por tipo de salto.
  • Esportivos = classificação sport ou staff → inclui piloto de tandem e câmera. Detalhado por tipo de salto.
  • Total Outros (vagas totais) = classificação other (ou sem classificação) → o que não é salto, como voo panorâmico. É um total separado (um nível acima, ao lado de "Total de saltos"), fora das vagas totais de saltos. Detalhado por tipo.
  • Retorno a Bordo = vagas marcadas como Retorno a Bordo (embarcou, decolou e voltou sem saltar). Categoria própria, fora de duplos/alunos/esportivos, detalhada pelo tipo de salto original (ex.: quantos tandens voltaram). A decolagem continua contando; o salto, não.

Para um tipo cair em Outros, marque a classificação do tipo de salto como Outro em Configurações → Tipos de Salto (ex.: Voo Panorâmico). O Retorno a Bordo não depende da classificação do tipo — é a marca da vaga que define a categoria.

Acesso: capability reports.rta.view (perfis admin, operational e rta). O menu Relatórios é um submenu — cada relatório tem sua própria capability, então relatórios diferentes podem ser liberados a perfis diferentes (ex.: futuros relatórios financeiros só para financial).


15. Combustível

O módulo Combustível é o "posto" da DZ: tanques, compras, abastecimentos e relatório. Guia completo em Combustível.

  • Tipos de combustível são um catálogo por DZ. Cada tipo é um registro próprio (referenciado por id), não uma lista fixa do sistema — a DZ cria os seus (pelo ➕ Criar novo tipo… no formulário do tanque ou pelo menu ⋮ → Tipos de combustível), e toda DZ já nasce com "Querosene (QAV-1)" cadastrado. Renomear não altera o histórico (movimentos antigos referenciam o id, não o nome). Excluir só é permitido quando o tipo nunca foi usado; em uso, o caminho é inativar (some das novas escolhas, o passado fica intacto). Nome duplicado é rejeitado.
  • Saldo do tanque é sempre derivado dos movimentos. Compras, transferências de entrada e sobras somam; abastecimentos, transferências de saída e perdas subtraem. Não existe edição direta de saldo — correção de conferência física é feita via Ajuste de estoque (sobra/perda, nunca zero).
  • Custeio FIFO por lote. Cada compra vira um lote (litros + preço daquela compra). Cada abastecimento consome os lotes mais antigos primeiro; o custo registrado é o custo real do combustível que estava no tanque, com rastreio de qual compra supriu cada litro. O Valor do estoque do painel é a soma do que resta em cada lote ao preço de cada um, e o Custo médio do estoque (Valor do estoque ÷ saldo) é o custo real por litro daquele tanque. Já o Custo de reposição é o preço da última compra do tipo de combustível — por isso é igual em todos os tanques do mesmo tipo, independente de em qual tanque a compra entrou: ele existe para sugerir o preço de venda (repor ao preço de hoje), não para custear o estoque.
  • Estorno devolve aos mesmos lotes. Estornar um movimento cria um lançamento inverso e, no caso de abastecimento, devolve os litros exatamente aos lotes de onde saíram — estoque e custo voltam ao estado anterior. Movimento estornado não pode ser estornado de novo.
  • Trocar o tipo de combustível de um tanque exige tanque zerado. Os lançamentos passados nunca mudam de tipo (cada compra/movimento guarda o tipo da época); a troca só é aceita com o estoque em zero — transfira ou ajuste antes. Transferência entre tanques continua exigindo o mesmo tipo nos dois lados.
  • Consumo interno resolve sem receita. No fechamento, abastecidas podem ser resolvidas como consumo interno: saem da fila "A precificar" sem nunca receber preço de venda — nenhuma receita é fabricada; o registro mantém apenas o custo FIFO. Relatórios mostram o custo normalmente e nada em receita/margem para essas linhas.
  • Fechamento pode debitar a carteira do comprador. Ao aplicar o preço, o operador escolhe: debitar a carteira do dono do avião (ou outra conta) com o total da venda em uma transação ("Combustível — fechamento…"), ou DZ sem cobrança (só precifica — quando a DZ absorve o combustível, ex. taxa fixa por decolagem). O débito é lançado depois da precificação: se falhar, os abastecimentos permanecem precificados e o sistema orienta a cobrar manualmente.
  • Sugestão de preço do fechamento cobre o custo real. O preço sugerido no Fechamento do mês é Σ(receita-alvo por abastecida) ÷ Σ(litros), onde a receita-alvo usa o custo FIFO real de cada abastecida × (1 + markup da política do tipo), preço fixo × litros, ou o próprio custo quando o tipo não tem política — arredondado para cima. Seleções com tipos/custos diferentes nunca geram sugestão abaixo do custo. A Política de venda (ver/editar) exige a permissão financeira do combustível; o preço sugerido resolvido continua disponível a quem opera.
  • Data do abastecimento herda a decolagem. Abastecimento vinculado a uma decolagem, lançado sem data explícita, assume a data/hora da decolagem (o lançamento pode ser feito no dia seguinte sem "mudar" o dia do consumo). A data de registro no sistema ("Lançado em") é guardada separadamente e exibida quando difere.
  • Editar abastecimento = estorno + relançamento (atômico), exibido como uma linha só. A ação Editar (tabela de Movimentos ou "Editar abastecimento" no card da decolagem) não altera o lançamento original: numa única operação, o original é estornado (litros de volta aos lotes FIFO) e um novo lançamento entra com os valores corrigidos. Na tela, a correção aparece como uma única linha com o selo "Alterado" e os valores finais — o original e o estorno ficam preservados no histórico (mesma apresentação das transações de carteira), sem poluir a lista. Estorno manual (cancelar um lançamento) continua mostrando as duas linhas: o original como "Estornado" e a linha de estorno.
  • Guard-rails de estoque: não dá para abastecer de tanque sem compra registrada (sem preço de custo não há FIFO), nem além do saldo; compra não pode exceder a capacidade do tanque.
  • Abastecimento de avião da DZ: preço de venda é opcional. Em branco, o movimento fica "A precificar" e entra no Fechamento do mês, onde a DZ aplica um preço por litro em lote aos pendentes e calcula a receita — espelha o acerto mensal com o dono do avião. Movimento já precificado não é precificado de novo.
  • Abastecimento avulso (aeronave de terceiros) é venda na hora. Exige cliente e/ou matrícula e preço obrigatório (sugerido pela política de venda). Não existe "a precificar" para terceiros.
  • Política de venda por tipo de combustível: Markup (%) sobre a última compra ou Preço fixo por litro → gera o Preço sugerido.
  • Transferência só entre tanques do mesmo tipo de combustível, com custo dos lotes preservado.
  • Planejado × realizado no manifesto. A flag "Precisa abastecer" da decolagem (planejamento/turnaround) é independente do registro de abastecimento — o card mostra o planejado e, do lado realizado, o selo com os litros junto ao ícone de bomba (ex.: "120 L"; o detalhe "Abastecido: N L" fica no tooltip). Registro pelo card, pelo painel ou pelo diálogo "Abastecidas do dia" (várias decolagens de uma vez, litros pré-preenchidos pelo consumo médio do avião).
  • Relatório Consumo de Combustível: horas voadas vêm da melhor fonte disponível — horímetroloads voados (só decolagens do mesmo dia do abastecimento) → intervalo no dia (relógio) — e nunca geram intervalo negativo; voos de dias anteriores sem abastecimento registrado não são atribuídos a um abastecimento posterior. Totais separam próprio × terceiro. Além da Margem (R$) existe a Margem % — percentual sobre o custo real (mesma convenção do fechamento e da lista de movimentos) — presente nas linhas, nos totais de grupo e de período, no card de Margem do topo, no CSV e na impressão. Nos totais, a base do percentual é o custo apenas dos abastecimentos já precificados, para que os "a precificar" não distorçam o número. Custo e margem (incl. Margem %) dependem de reports.fuel_consumption.financial; sem a capability, o relatório mostra litros, horas e receita.
  • RBAC: admin e operacional gerenciam; financeiro visualiza; demais perfis não veem o módulo. A parte financeira do combustível é uma capability separada — fuel.financial — que libera o lado do custo (custo por litro, custo total, valor do estoque, custo de reposição e margem) nas telas de Combustível e Fechamento do mês; no relatório, as colunas de custo/margem têm capability própria, reports.fuel_consumption.financial. O preço de venda não é gateado (quem vende precisa do preço). Padrão: financeiro (e admin) têm fuel.financial; operacional opera sem ver custos; o admin sempre vê tudo. Tudo editável na tela de Acessos (RBAC).
  • Linha "Acesso" dinâmica nos cabeçalhos. O cabeçalho das páginas Combustível e Fechamento do mês reflete o RBAC real da DZ (inclusive edições feitas em Acessos), no formato "Gerenciam: … · Visualizam: … · Veem custos: …" — não é texto fixo.
  • Filtro "Vínculo" (movimentos e fechamento). Nos filtros da aba Movimentos e da tela Fechamento do mês: Todos / Só de decolagem / Só fora de decolagem. Permite fechar o mês em partes — um fechamento da operação (abastecimentos ligados a decolagens) e outro dos avulsos, com preços diferentes.
  • Bloco de venda na lista de movimentos. Três colunas juntas: Venda (valor total), Venda/L (preço por litro cobrado) e Margem (% sobre o custo real, exibida em vermelho quando negativa). Venda e Venda/L são visíveis para quem vê o módulo (quem vende precisa do preço); a Margem exige a capability financeira (fuel.financial).
  • Composição do estoque (diálogo por tanque). No card do tanque, o menu ⋮ → "Composição do estoque" (ou um clique na barra de nível) abre a visão do que está dentro do tanque agora, agrupado por preço pago: barra empilhada + lista em ordem de consumo FIFO (o primeiro é o próximo a sair) com preço/litro, litros, % do tanque, valor, data e fornecedor/NF quando houver; no rodapé, total, custo médio e custo de reposição. É informação de custo → visível só com a capability financeira do combustível (fuel.financial).
  • Preço de venda não é sugerido ao abastecer avião da DZ. O campo do diálogo Abastecer avião abre sempre em branco — a precificação do avião próprio é feita no Fechamento do mês (onde a sugestão inteligente existe). O Abastecimento avulso continua com o preço sugerido pela política de venda, por ser venda imediata a terceiros.
  • Horário sugerido do abastecimento por decolagem. Quando o abastecimento está vinculado a uma decolagem (portal e manifesto), a data/hora vem preenchida com o horário da decolagem menos 3 minutos (o avião é abastecido pouco antes de decolar) e é editável — inclusive no portal.
  • Tanque principal. No máximo um por DZ (marcar outro desmarca o anterior); com um único tanque, ele é principal automaticamente. É o tanque que o Portal do Combustível destaca na tela inicial — com vários tanques, o portal mostra só o principal (com "Ver todos os tanques" para a lista completa) e exige a escolha explícita do tanque ao registrar um abastecimento (sem pré-seleção, para evitar lançamento no tanque errado). Com um só tanque, a escolha é automática. No painel, o principal aparece com o selo "Principal".
  • Horários no fuso da DZ. Os horários dos abastecimentos são exibidos no horário local da DZ em todas as telas (portal e admin) — inclusive os avulsos, que antes podiam aparecer deslocados.
  • Portal do Combustível (função Abastecedor). O portal chama-se Portal do Combustível; a função da pessoa continua Abastecedor — é ela que dá o acesso. Concedido no cadastro da Pessoa (toggle "Acesso ao Portal do Combustível", mesmo padrão do Portal do Aeronauta — não depende de ser atleta) ou pelo perfil Abastecedor na Equipe; entra no funil de portais do login (acesso único → vai direto; múltiplos → tela de seleção, com portal padrão). A tela mostra todos os lançamentos do dia (inclusive avulsos, de outros operadores ou do manifesto), com o nome de quem lançou; a edição é restrita aos próprios lançamentos e só os recentes (até 36 horas) — lançamento de outra pessoa ou antigo só é corrigido pela equipe no admin (edição/estorno). O card do tanque mostra o saldo e o total utilizado no dia, em litros. O portal não tem lado financeiro: nunca mostra custo, preço nem valor de estoque — só litros; todo abastecimento registrado por ele nasce "A precificar" e segue o fluxo normal do fechamento do mês.
  • Regulatório (awareness): vender combustível a aeronave de terceiros é revenda (Resolução ANP 936/2023). O sistema separa consumo próprio × venda a terceiro para a prestação de contas; a regularização é responsabilidade da DZ.

Notas de manutenção (para devs)

Estas não afetam o usuário final, mas evitam pegadinhas no desenvolvimento.

  • PeopleRepository.Update tem whitelist de colunas (Select(...)). Colunas novas na Pessoa não persistem silenciosamente até serem adicionadas à lista. Se um campo novo "não salva", é aqui.
  • O guia técnico do motor de cobrança (com diagramas) está em Motor de Cobrança (anexo técnico).