WEBSOCKETdoctors.updated

Médico Atualizado

Evento WebSocket para notificar em tempo real quando um médico é atualizado. Este evento é emitido automaticamente pelo servidor após atualizar um médico no banco de dados (com validação de agendamentos e atualização de procedimentos), 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 atualizem o médico na 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 um médico é atualizado, todos os clientes da conta recebem o médico completo com dados atualizados e procedimentos vinculados.

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: doctors.updated

1

Serviço atualiza médico e emite evento interno

Quando um médico é atualizado via API, o doctor.service.ts atualiza o médico no banco (com validação de agendamentos e atualização de procedimentos) e emite evento interno:

// doctor.service.ts
// ... valida agendamentos e atualiza médico no banco ...

// Emite evento interno após atualizar o médico
this.eventEmitter.emit('doctors.updated', {
  doctor: doctor, // Médico completo com relacionamentos atualizados (doctorProcedures e procedures)
  payload: payload,
});
O que faz: atualiza médico no banco e emite evento interno para propagação via WebSocket
Validação: verifica se há agendamentos com procedimentos que serão removidos antes de atualizar
Atualização atômica: dados do médico e procedimentos são atualizados em uma única operação
Dados do evento: médico completo com relacionamentos atualizados (doctorProcedures e procedures) e payload
Quando é chamado: quando um médico é atualizado via API (método update())
2

Listener propaga evento via WebSocket

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

// doctors.listener.ts
@OnEvent('doctors.updated')
async handleDoctorsUpdated(data: {
  doctor: DoctorResponserDto;
  payload: PayloadTokenDto;
}) {
  try {
    // Propaga via WebSocket para todos os clientes da conta
    await this.gateway.notifyOnEvent(
      'doctors.updated',
      data.doctor, // Objeto DoctorResponserDto completo
      data.payload,
    );
    
    this.logger.debug(
      `Medico ${data.doctor.id} atualizado e propagado via WebSocket para conta ${data.payload.accountId}`,
    );
  } catch (error) {
    this.logger.error(
      `Erro ao propagar evento doctors.updated:`,
      error,
    );
  }
}
O que faz: escuta evento interno e propaga via WebSocket
Broadcast: notifica todos os clientes da mesma conta
Dados enviados: objeto DoctorResponserDto completo (com dados atualizados e procedimentos vinculados)
Log: registra ID do médico e accountId
Tratamento de erro: loga erros sem quebrar o fluxo
3

Gateway faz broadcast para todos da conta

O método `notifyOnEvent` envia o evento 'doctors.updated' 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.'
// Evento: 'doctors.updated' (está na lista de eventos permitidos - linha 105)
// Dados: objeto DoctorResponserDto completo (com dados atualizados e procedimentos vinculados)
// Todos os clientes conectados da mesma accountId recebem o evento
Evento emitido: 'doctors.updated' (está na lista de eventos permitidos)
Dados enviados: objeto DoctorResponserDto completo (com dados atualizados e procedimentos vinculados)
Quem recebe: todos os clientes conectados da mesma accountId
Room format: orders.account.{accountId}
Sincronização: todos os clientes recebem a notificação simultaneamente
4

Cliente recebe evento e atualiza médico na lista

O componente ConfigListener.tsx escuta o evento e atualiza o médico existente na lista:

// ConfigListener.tsx
socket.on('doctors.updated', (doctor: Doctor) => {
  // Atualiza médico existente na lista (substitui o antigo pelo novo)
  setDoctors((prev) =>
    prev.map((d) => (d.id === doctor.id ? doctor : d))
  );
});

// Cleanup ao desmontar
return () => {
  socket.off('doctors.created');
  socket.off('doctors.deleted');
  socket.off('doctors.updated');
};
O que faz: escuta evento e atualiza médico existente na lista
Atualiza na lista: setDoctors((prev) => prev.map(...)) substitui o médico antigo pelo novo
Mantém ordem: a posição na lista é preservada (map mantém ordem original)
Substituição completa: substitui completamente o médico antigo pelo novo (com dados atualizados)
Atualiza estado: setDoctors() atualiza a lista e re-renderiza
Atualiza UI: tabela de médicos é atualizada automaticamente
Cleanup: remove listeners 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": 1,
  "name": "Dr. João Silva",
  ...
{
  "id": 1,
  "name": "Dr. João Silva",
  "crm": "12345",
  "email": "joao.silva@example.com",
  "phone": "(81) 99999-9999",
  "isBusy": false,
  "accountId": 1,
  "createdAt": "2025-01-23T10:30:00.000Z",
  "updatedAt": "2025-01-23T11:00:00.000Z",
  "doctorProcedures": [
    {
      "id": 1,
      "procedure": {
        "id": 3699,
        "name": "Ultrassom: Tireoide",
        "price": "100"
      }
    },
    {
      "id": 2,
      "procedure": {
        "id": 3700,
        "name": "Ultrassom: Transfontanela",
        "price": "110"
      }
    }
  ]
}