Skip to content

Módulo de Agendamento

Documentação técnica detalhada do módulo de agendamento, incluindo regras de negócio, validações e fluxos.

Regras de Negócio

Validações na Criação

Ao criar um agendamento, as seguintes validações são aplicadas em ordem:

  1. Profissional ativo na unidade selecionada
  2. Disponibilidade do profissional: O horário deve estar dentro da grade de disponibilidade configurada
  3. Sem conflito de agendamento: O profissional não pode ter outro agendamento ativo no mesmo horário
  4. Disponibilidade da sala (se informada): A sala não pode estar em uso no mesmo horário
  5. Duração coerente: O horário de fim é calculado com base na duração do procedimento

Grade de Disponibilidade

Cada profissional define sua grade por dia da semana, por unidade:

  • Intervalos de 15 minutos mínimos
  • Suporte a múltiplos turnos no mesmo dia (ex: 08h–12h e 14h–18h)
  • Exceções por data sobrescrevem a regra semanal (férias, feriados)
  • Alteração da grade não cancela agendamentos existentes — apenas exibe conflito

Máquina de Estados

Transições permitidas e quem pode executá-las:

DeParaQuem pode
AGENDADOCONFIRMADOReceptionist, Admin, Owner
AGENDADOCANCELADOReceptionist, Admin, Owner
CONFIRMADOEM_ATENDIMENTOReceptionist, Admin, Owner
CONFIRMADOCANCELADOReceptionist, Admin, Owner
EM_ATENDIMENTOCONCLUÍDOProfessional (próprio), Admin, Owner
EM_ATENDIMENTOCANCELADOAdmin, Owner
AGENDADONO_SHOWReceptionist, Admin, Owner
CONFIRMADONO_SHOWReceptionist, Admin, Owner

Campos imutáveis após criação: tenantId, patientId, professionalId.

Cancelamento

Ao cancelar um agendamento:

  • O motivo de cancelamento é obrigatório
  • O status muda para CANCELADO
  • Uma notificação é enviada ao paciente (quando e-mail disponível)
  • O slot é liberado imediatamente na agenda

Conclusão e Faturamento

Ao marcar um agendamento como CONCLUÍDO:

  • Uma fatura é gerada automaticamente com os itens do procedimento
  • O profissional é notificado (in-app)
  • O prontuário está disponível para preenchimento

Disponibilidade de Slots

Consulta de Disponibilidade

GET /availability
Query params:
  professional_id: UUID (obrigatório)
  date: YYYY-MM-DD (obrigatório)
  procedure_id: UUID (obrigatório)
  unit_id: UUID (obrigatório)

Response 200:
{
  "slots": [
    { "start_at": "2026-05-20T09:00:00Z", "end_at": "2026-05-20T09:30:00Z", "available": true },
    { "start_at": "2026-05-20T09:30:00Z", "end_at": "2026-05-20T10:00:00Z", "available": false }
  ]
}

O algoritmo de disponibilidade:

  1. Carrega a grade de disponibilidade do profissional para o dia da semana
  2. Verifica se existe exceção para a data específica
  3. Gera todos os slots possíveis no intervalo configurado
  4. Remove slots que colidem com agendamentos existentes (status ≠ CANCELADO)
  5. Remove slots que colidem com bloqueios de agenda
  6. Retorna o array com flag available por slot

Cache de Disponibilidade

A disponibilidade de agenda é cacheada no Redis por 5 minutos para evitar queries repetidas em alta carga. O cache é invalidado quando:

  • Um novo agendamento é criado para o profissional
  • Um agendamento é cancelado
  • A grade de disponibilidade é alterada

Notificações do Módulo

Eventos disparados via Hangfire (fila background):

EventoDelayAção
Criação de agendamentoImediatoE-mail de confirmação ao paciente
Criação de agendamento24h antesE-mail de lembrete ao paciente
Criação de agendamento2h antesE-mail de lembrete ao paciente
CancelamentoImediatoE-mail de cancelamento ao paciente

Tempo Real (SignalR)

O hub AppointmentHub emite eventos via SignalR para todos os clientes da organização autenticada:

appointment.created  → Novo agendamento criado
appointment.updated  → Status ou dados alterados
appointment.cancelled → Agendamento cancelado

O frontend Angular assina esses eventos e atualiza o calendário em tempo real sem polling.

Endpoints da API

MétodoEndpointPapel mínimoDescrição
GET/appointmentsViewerListar agendamentos (com filtros)
POST/appointmentsReceptionistCriar agendamento
GET/appointments/:idViewerDetalhe de um agendamento
PATCH/appointments/:id/statusReceptionistAlterar status
GET/availabilityViewerConsultar slots disponíveis

Exemplo de Criação

http
POST /appointments
Authorization: Bearer {token}
Content-Type: application/json

{
  "patient_id": "uuid-do-paciente",
  "professional_id": "uuid-do-profissional",
  "procedure_id": "uuid-do-procedimento",
  "unit_id": "uuid-da-unidade",
  "room_id": "uuid-da-sala",
  "start_at": "2026-05-25T10:00:00Z",
  "notes": "Paciente com alergia a látex"
}

Possíveis Erros

Código HTTPErroSituação
409SLOT_NOT_AVAILABLEHorário já ocupado pelo profissional
409PROFESSIONAL_UNAVAILABLEProfissional fora da grade de disponibilidade
409ROOM_CONFLICTSala já em uso no horário
422PATIENT_NOT_FOUNDID de paciente inválido
422PROFESSIONAL_NOT_IN_UNITProfissional não atua na unidade informada

Funcionalidades Planejadas (V1 e V2)

  • [ ] Drag & drop para reagendamento no calendário
  • [ ] Visualização mensal do calendário
  • [ ] Agendamentos recorrentes (/appointments/:id/recurrence)
  • [ ] Lista de espera com preenchimento automático de slot
  • [ ] Lock otimista de 5 minutos no slot (portal do paciente)
  • [ ] Notificações via WhatsApp

Desenvolvido com ❤️ pela equipe FastGivr.