Skip to content

Ciclo de retirada — a máquina de estados do aluno ​

O que é este documento — a descrição autoritativa da máquina de estados de retirada de um aluno no ionCLASS: os 6 estados de retirada, quem pode avançá-los, como o hardware de controle de acesso e o operador se reconciliam sem duplicar a saída, e o que acontece nas bordas (pular estados, timeout, saída não sinalizada). É o coração do produto — todo o resto (portaria, painel público, app do responsável) apenas observa esta máquina.


1. Os 6 estados ​

O estado de retirada é uma propriedade viva do aluno. A progressão normal ("para frente") é sequencial e ordenada — cada estado tem um índice de 0 a 5 que a lógica de transição usa para calcular saltos:

ÍndiceEstadoQuem tipicamente entra aqui
0Fora da escolaInício/fim do dia (a baixa automática leva todos para cá); também destino de uma saída não sinalizada
1Na escolaEntrada registrada (catraca ou operador)
2Aguardando retiradaResponsável sinalizou "Estou Chegando"
3Em preparaçãoOperador começou a separar a criança
4ProntoCriança na porta; catraca liberada + responsáveis notificados
5RetiradoSaída confirmada (operador ou controle de acesso)
        ┌──────────────── progressão normal (operador, sequencial) ────────────────┐
        │                                                                          │
   Fora da escola ──▶ Na escola ──▶ Aguardando ──▶ Em preparação ──▶ Pronto ──▶ Retirado
       (0)              (1)           (2)              (3)             (4)         (5)
        ▲                              │                │              │            ▲
        │                              └────────────────┴──────────────┘            │
        │                    HARDWARE pode PULAR direto p/ "Retirado" ──────────────┘
        │                    (saída do controle de acesso c/ sinal de chegada ativo;
        │                     estados pulados → auditoria de "estados pulados")
        │
        └──── saída NÃO sinalizada: leitura de catraca SEM sinal de chegada ativo
              (saída → "Fora da escola", não "Retirado"; auditoria de "saída não sinalizada")

"Fora da escola" é ao mesmo tempo o ponto de partida do dia e o destino de uma saída física sem retirada sinalizada (ver §5).

1.1 Presença real, separada da etapa ​

O estado de retirada descreve a etapa da saída, não a presença física. A presença é um atributo próprio do aluno, que só muda com movimento real:

  • liga com uma entrada registrada (leitura no leitor de entrada ou "registrar entrada" manual no painel);
  • desliga com uma saída (retirada confirmada, saída não sinalizada, saída solo autorizada) e com a baixa automática do dia;
  • não muda com o sinal de chegada nem com os passos do operador.

O responsável pode avisar a chegada para qualquer filho, esteja ele marcado dentro ou fora da escola. Um filho que não entrou vai para "Aguardando retirada" como os demais e aparece no quadro da portaria com o selo "Sem registro de entrada". App e painel continuam mostrando "Fora da escola" para ele, porque informar uma presença que não aconteceu é pior do que deixar a escola conferir.

Se esse aluno passa no leitor de entrada durante o sinal, só a presença liga: ele continua na mesma etapa e na mesma coluna do quadro, o selo some e app e painel passam a mostrar "Na escola". A versão do estado sobe para todos os clientes aceitarem a mudança, mas o carimbo da etapa não muda, então o tempo em "Pronto" não reinicia.

É a presença que alimenta o botão contextual "registrar entrada/saída" do painel, o indicador "Na escola"/"Fora da escola" do app (incluindo a pré-seleção do "Estou Chegando", que marca só os filhos presentes) e o KPI de presentes do dashboard.

Toda mudança de estado transmite StudentStateChanged em tempo real — ver tempo real. Os rótulos em pt-BR são usados nas superfícies admin/relatórios. Glossário dos termos: glossário.


2. Transições permitidas ​

Há dois caminhos para mudar o estado, com regras diferentes:

2.1 Operador — avanço sequencial ​

O único avanço sancionado para os passos do operador (aguardando retirada → em preparação → pronto) é o avanço sequencial. A regra é estrita:

  • Só um passo por vez, para frente. O próximo estado precisa ser exatamente o índice atual + 1. Qualquer salto ilegal (pular etapa, ou voltar) é recusado com 422 ("Transição de estado inválida: {from} → {to}.").
  • A transição final "Pronto → Retirado" NÃO passa por aqui. Ela é dual-source e é resolvida exclusivamente pelo resolvedor de corrida entre fontes (ver §4). É a razão de o avanço sequencial cobrir só até "Pronto".

2.2 Hardware — pode pular ​

Um evento exit do controle de acesso é autoritativo e pode saltar de "aguardando retirada" ou "em preparação" direto para "Retirado". Os estados intermediários pulados são registrados numa auditoria de "estados pulados", preservando a trilha de que a criança nunca passou visivelmente por "em preparação"/"pronto".


3. Concorrência — lock otimista ​

O mesmo aluno pode ser tocado ao mesmo tempo pelo operador, pelo hardware e pela rotina de reversão. O controle de concorrência é um lock otimista apoiado em dois dados:

  • a versão do estado — inteiro incrementado a cada mudança bem-sucedida;
  • o carimbo da última mudança.

O avanço grava a mudança só se a versão ainda for a que ele leu. Se a versão já mudou nesse intervalo, alguém alterou o estado antes → 409 ("O estado do aluno mudou em outra ação. Recarregue a fila."). O cliente recarrega e tenta de novo. Essa versão também é o eixo de reconciliação do tempo real: ela nunca regride (ver tempo real).


4. A corrida dual-source (Decisão 8) ​

A transição final "Pronto → Retirado" tem duas fontes possíveis e simultâneas: o operador confirma na portaria ou o controle de acesso lê a credencial na catraca. Para não duplicar a saída, ambos os caminhos afunilam para um único resolvedor de corrida entre fontes, onde o lock otimista decide o vencedor em um só lugar.

  Operador (confirma na portaria)        ──┐
                                           ├──▶  Resolvedor de corrida  ──▶  cria 1 retirada + avança estado
  Controle de acesso (saída na catraca)  ──┘        (transação + trava no aluno)

4.1 Chave de idempotência (bucket de 5 min) ​

A reconciliação usa uma idempotency key determinística compartilhada pelas duas fontes:

sha256( id do aluno | id da escola | 'exit' | floor(unix/300)*300 )

O floor(unix/300)*300 agrupa o evento numa janela de 5 minutos. Uma confirmação do operador e uma leitura da catraca para o mesmo aluno dentro do mesmo bucket geram a mesma chave (FR-057). O bucket usa deliberadamente o tempo atual, mesmo quando o evento carrega um horário anterior (registro manual), justamente para que as duas fontes ainda batam.

4.2 Quem chega primeiro vence ​

Dentro de uma transação, o resolvedor trava o aluno e procura uma retirada já registrada com aquela chave:

  • Não existe → esta fonte venceu: cria a retirada com o seu método, avança o aluno para "Retirado" (+ auditoria de "estados pulados" se o hardware pulou etapas), emite PickupConfirmed/PublicPickupConfirmed, notifica os responsáveis (retirada confirmada) e termina o sinal de chegada ativo (motivo: retirado).
  • Já existe → esta fonte perdeu a corrida: nenhuma retirada nova é criada. Grava-se uma auditoria de confirmação secundária correlacionada à retirada vencedora e devolve-se a existente marcada como secundária. No lado do operador, isso vira um 409 carregando a retirada que já fechou; no lado do hardware, se o aluno já está "Retirado", a confirmação secundária é gravada direto, sem sequer entrar no resolvedor.

O resultado é sempre exatamente uma retirada por saída, com o método de quem chegou primeiro, e uma trilha de auditoria da segunda fonte como confirmação — nunca uma duplicata.


5. Saída não sinalizada ​

Uma leitura de catraca (exit, método hardware) sem um sinal de chegada ativo não é uma retirada: nenhum responsável sinalizou a saída. É uma partida física apenas. Nesse caso o resolvedor:

  • ainda cria a retirada (método hardware) — mantendo intacta a maquinaria de idempotência/corrida;
  • manda o aluno para "Fora da escola" (e não "Retirado");
  • grava auditoria de "saída não sinalizada";
  • não dispara PickupConfirmed nem a notificação de retirada confirmada (o hardware já notificou a partida física pela saída);
  • revoga a liberação da catraca, já que a criança saiu.

Caso relacionado: saída solo autorizada — se o aluno tem uma liberação antecipada solo aprovada para hoje, a leitura vira uma partida autorizada (→ "Fora da escola", auditoria de "saída solo autorizada", consome o passe), também sem notificação de retirada confirmada. Ver §6 (método liberação solo).


6. Ao atingir "Pronto" — o que isso significa ​

"Pronto" não é só um rótulo bonito no quadro: é a promessa de que a criança pode fisicamente sair. Quando o avanço leva o aluno a "Pronto", duas coisas acontecem além do broadcast:

  1. Notifica os responsáveis (retirada pronta).
  2. Libera a catraca — envia o comando de liberação ao controle de acesso. Sem isso o quadro seria "teatro": vivo e bonito, sem efeito numa catraca que é default-deny. A chamada é enqueue-only e tolerante a falha, então a transição nunca depende do hardware responder. Detalhes do outbound: comandos outbound.

6.1 Quando o responsável atrasa ​

O operador pode estender a liberação (+30 min) para quem está em "Pronto" e ainda não foi retirado. Essa extensão deixou de ser um gesto mudo: ela acende o marcador "em atraso" no aluno e notifica os responsáveis uma única vez.

O marcador é um atributo do aluno, não um estado de retirada: os estados são uma sequência ordinal espelhada pelo monitor e pelo controle de acesso, então um estado a mais no meio quebraria os três lados. O aluno segue em "Pronto" e segue liberado; a versão do estado não muda, de propósito, para não conflitar com um operador arrastando o cartão.

O marcador é apagado na retirada, na revogação da liberação, em qualquer mudança de estado e na reversão automática descrita abaixo.

O marcador aparece nas duas telas da saída: no monitor de portaria (selo no cartão) e no painel público (selo ao lado de "Pronto para sair", no card do aluno com sinal de chegada ativo — sem sinal, o painel público não tem card para acender). Marcar e apagar o marcador transmitem nos dois canais, para as outras abas e o kiosk atualizarem sem refresh.


7. Reversão automática de "Pronto" preso ​

Um aluno pode ficar preso em "Pronto" (responsável não apareceu). Como "Pronto" implica uma liberação de catraca viva, um "Pronto" velho é ao mesmo tempo uma mentira no quadro e uma credencial aberta. Uma rotina agendada (a cada 5 min) corrige isso:

  • seleciona alunos em "Pronto" parados há mais que o tempo limite configurado (padrão 60 min);
  • devolve o aluno à presença real ("Na escola", ou "Fora da escola" para quem nunca registrou entrada; ver §1.1) com uma escrita condicional na versão e no estado — se perder a corrida para uma retirada real, pula o aluno graciosamente, sem efeitos colaterais;
  • revoga a liberação da catraca, notifica (retirada revertida) e transmite StudentStateChanged com motivo "tempo de espera esgotado" para o monitor poder alertar sobre a remoção do cartão;
  • grava auditoria de "tempo de espera esgotado".

Ver tarefas agendadas para o agendamento e observabilidade.

7.1 Baixa automática do dia ​

No horário de baixa automática diária da escola (padrão 23:59, no fuso da escola; configurável e desativável por escola), uma rotina fecha o dia:

  • encerra todos os sinais de chegada ainda abertos da escola — inclusive os de alunos Em preparação ou Pronto, que o tempo limite do sinal não encerra; um sinal pelo qual alguém já saiu termina como retirado;
  • leva todos os alunos que não estão em "Fora da escola" para "Fora da escola", de qualquer estado (Na escola, Aguardando, Em preparação, Pronto ou Retirado) e mesmo sem sinal. É a única transição automática que salta para trás a partir de qualquer estado;
  • usa a mesma escrita condicional na versão e no estado: se o aluno mudou no mesmo instante, ele é pulado;
  • revoga a liberação da catraca de quem estava em "Pronto" e transmite StudentStateChanged com motivo "baixa do dia"; os responsáveis não recebem push;
  • grava uma auditoria por escola ("Baixa automática do dia") com as contagens.

7.2 Sinal encerrado sem retirada ​

Quando o sinal termina sem a criança sair, o aluno volta à presença real (§1.1): "Na escola" se registrou entrada, "Fora da escola" se não. Vale para todos os caminhos:

  • o responsável cancela o aviso;
  • o sinal expira pelo tempo limite da escola;
  • a portaria revoga a liberação de um "Pronto";
  • o responsável é bloqueado na escola;
  • a reversão automática de "Pronto" vence;
  • a portaria tira o aluno do sinal.

8. Métodos de retirada ​

O método da retirada registra como aquela saída foi confirmada:

MétodoConfirmação visual?Quando se aplica
Visual✅ simOperador confirmou visualmente (foto lado-a-lado, FR-056) — caso padrão
Visual (na hora)✅ simRetirada visual de quem chegou sem passar pela fila de sinal
Hardware❌ nãoControle de acesso leu a credencial na catraca; identidade já validada no leitor (Decisão 8, cidadão de primeira classe)
Liberação solo❌ nãoAluno com liberação antecipada solo aprovada — sai sozinho, sem match de identidade

A confirmação visual é exigida só para "Visual" e "Visual (na hora)". Na confirmação do operador, se o aluno tem uma liberação solo ativa o método vira "Liberação solo" (e o passe é marcado como usado quando a corrida resolve); senão é "Visual". O controle de acesso sempre entra com "Hardware".


9. Trilha de auditoria — resumo das ações ​

Cada momento do ciclo deixa registro. As principais ações de auditoria:

AçãoQuando
Avanço de estadoAvanço sequencial do operador
Retirada confirmadaFonte vencedora fechou a retirada
Confirmação secundáriaSegunda fonte chegou depois (não duplica)
Estados puladosHardware pulou estados intermediários
Saída não sinalizadaSaída física sem sinal de chegada
Saída solo autorizadaSaída solo autorizada por passe
Tempo de espera esgotadoReversão automática de "Pronto" preso
Baixa automática do diaFechamento diário da escola (uma por escola, com contagens)

Ver também ​

Documentação do ionCLASS