WEBSOCKETappointments.created

Agendamento Criado

Evento WebSocket para notificar em tempo real quando um novo agendamento é criado. Este evento é emitido automaticamente pelo servidor após criar um ou múltiplos agendamentos no banco de dados, propagando a notificação para todos os clientes conectados da mesma conta. O servidor faz broadcast do evento para todos os clientes da mesma accountId, permitindo que todos adicionem o novo agendamento à lista simultaneamente. Este evento não é iniciado pelo frontend; é um evento unidirecional (servidor → clientes) usado exclusivamente para sincronização de UI em tempo real. Quando múltiplos procedimentos são selecionados, múltiplos appointments são criados (um por procedimento) e múltiplos eventos são emitidos, um para cada appointment criado.

Access Token

Para realizar requisições GET, POST, PUT, DELETE e PATCH nos endpoints da API você precisa de uma chave de autorização. Chamamos essa chave de accessToken.

Para ter acesso ao accessToken, é necessário que o usuário master da licença efetue a liberação deste pela interface do ImageMais Clinic. O accessToken tem validade de 1 hora.

Headers

AuthorizationOBRIGATÓRIO
Tipo:string
Token de autenticação no formato Bearer {accessToken}. O token deve ser enviado durante o handshake de conexão WebSocket.

Parâmetros

Este método não possui parâmetros.

Fluxo passo a passo: appointments.created

1

Serviço cria appointments no banco e emite eventos

O appointments.service.ts cria um ou múltiplos appointments no banco de dados e emite evento para cada um criado:

// appointments.service.ts
// Cria múltiplos appointments (um por procedimento selecionado)
const appointments = await Promise.all(
  procedures.map(async (procedure) => {
    // Cria appointment no banco dentro de transação
    return await this.prisma.appointments.create({
      data: {
        date: appointmentData.date,
        startTime: appointmentData.startTime,
        endTime: appointmentData.endTime,
        doctorId: appointmentData.doctorId,
        patientId: appointmentData.patientId,
        // ... outros campos
      },
      include: {
        doctor: true,
        patient: { include: { contact: true } },
        status: true,
        appointmentProcedures: { include: { procedure: true } },
      },
    });
  })
);

// Emite evento para cada appointment criado
appointments.forEach((appointment) => {
  this.eventEmitter.emit('appointments.created', {
    appointment: appointment,
    payload: payload,
  });
});
O que faz: cria appointments no banco de dados
Múltiplos appointments: cria um appointment por procedimento selecionado
Transação: criação acontece dentro de transação do Prisma (garantia de consistência)
Dados completos: cada appointment inclui relacionamentos (doctor, patient, status, procedures)
Emite evento: emite 'appointments.created' para cada appointment criado
Quando é chamado: após validações de conflitos de horário e criação bem-sucedida no banco
2

Listener propaga evento via WebSocket

O appointments.listener.ts escuta o evento interno e propaga via WebSocket para todos os clientes da conta:

// appointments.listener.ts
@OnEvent('appointments.created')
async handleAppointmentsCreated(data: {
  appointment: AppointmentResponseDto;
  payload: PayloadTokenDto;
}) {
  try {
    // Propaga via WebSocket para todos os clientes da conta
    await this.gateway.notifyOnEvent(
      'appointments.created',
      data.appointment,
      data.payload,
    );
    
    this.logger.debug(
      `Agendamento ${data.appointment.id} criado e propagado via WebSocket para conta ${data.payload.accountId}`,
    );
  } catch (error) {
    this.logger.error(
      `Erro ao propagar evento appointments.created:`,
      error,
    );
  }
}
O que faz: escuta evento interno e propaga via WebSocket
Broadcast: notifica todos os clientes da mesma conta
Dados enviados: objeto AppointmentResponseDto completo
Múltiplos eventos: pode ser chamado múltiplas vezes (um evento por appointment criado)
Tratamento de erro: loga erros sem quebrar o fluxo
3

Gateway faz broadcast para todos da conta

O método `notifyOnEvent` envia o evento 'appointments.created' para todos os sockets da mesma accountId:

// accounts.gateways.ts
async notifyOnEvent(
  event: string,
  data: any,
  payload: PayloadTokenDto,
): Promise<any> {
  if (this._events.includes(event)) {
    // Envia para todos os clientes da mesma conta
    this.server
      .to(`${this.room}${payload.accountId}`)
      .emit(event, data);
  }
}

// this.room = 'orders.account.'
// Todos os clientes conectados da mesma accountId recebem o evento 'appointments.created'
Evento emitido: 'appointments.created' (está na lista de eventos permitidos)
Dados enviados: objeto AppointmentResponseDto completo
Quem recebe: todos os clientes conectados da mesma accountId
Múltiplos eventos: pode receber múltiplos eventos (um por appointment criado)
Sincronização: todos os clientes recebem a notificação simultaneamente
4

Cliente recebe evento e adiciona à lista

Todos os clientes conectados da mesma conta recebem o evento 'appointments.created' e adicionam o agendamento à lista:

// AppointmentsView.tsx
socket.on('appointments.created', (appointment: Appointment) => {
  // Adiciona à lista (no final)
  setAppointments((prev) => [...prev, appointment]);
});

// Remove listener ao desmontar componente
useEffect(() => {
  return () => {
    socket.off('appointments.created');
    socket.off('appointments.status.changed');
    socket.off('appointments.updated');
  };
}, []);
Quem recebe: todos os clientes conectados da mesma conta
O que faz: adiciona agendamento à lista (no final)
Validações: adiciona diretamente sem validações adicionais
Múltiplos eventos: pode receber múltiplos eventos e adiciona cada um à lista
Sincronização: todos os clientes veem a adição simultaneamente
Atualização de UI: lista é atualizada automaticamente em todos os clientes
Cleanup: remove listener ao desmontar para prevenir memory leaks

Request URL

ws://api-dev.imagemais.com
{
  "message": "Este evento é emitido automaticamente pelo servidor (não requer request body)"
}
{
  "message": "Este evento é emitido automaticamente pelo servidor (não requer request body)"
}

Respostas

{
  "id": 123,
  "date": "2025-01-23T00:00:00.000Z",
  ...
{
  "id": 123,
  "date": "2025-01-23T00:00:00.000Z",
  "startTime": "09:00",
  "endTime": "09:15",
  "notes": "Observações sobre o agendamento",
  "accountId": 1,
  "createdAt": "2025-01-23T10:00:00.000Z",
  "updatedAt": "2025-01-23T10:00:00.000Z",
  "deletedAt": null,
  "doctor": {
    "id": 1,
    "name": "Dr. Victor"
  },
  "patient": {
    "id": 456,
    "name": "João Silva",
    "contact": {
      "phone": "(81) 99999-9999"
    }
  },
  "status": {
    "id": 1,
    "name": "Agendado",
    "color": "#ffc107"
  },
  "appointmentProcedures": {
    "procedure": {
      "id": 3699,
      "name": "Ultrassom: Tireoide",
      "price": "100"
    }
  }
}