appointments.servingAgendamento Em Atendimento
Evento WebSocket para notificar em tempo real quando um agendamento entra em atendimento. Este evento é emitido automaticamente pelo servidor quando um agendamento muda de status para EM_ATENDIMENTO, 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 removam o agendamento da fila de espera simultaneamente. Este evento não é iniciado pelo frontend; é um evento unidirecional (servidor → clientes) usado exclusivamente para sincronização de UI em tempo real. Antes de emitir o evento, o servidor atualiza o médico como ocupado (isBusy: true) e garante o vínculo do appointment com o médico dentro de uma transação atômica.
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
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
Authorization | string | Sim | Token de autenticação no formato Bearer {accessToken}. O token deve ser enviado durante o handshake de conexão WebSocket. |
AuthorizationOBRIGATÓRIOParâmetros
Este método não possui parâmetros.
Fluxo passo a passo: appointments.serving
Listener escuta mudança de status para EM_ATENDIMENTO
O InServiceAppointmentListener escuta o evento interno 'appointments.status.change' e processa quando o status muda para EM_ATENDIMENTO:
// in-service-appointment.ts
@OnEvent('appointments.status.change')
async handleAppointmentsStatusChange(event: AppointmentStatusChangeEvent) {
// Só processa se action === EM_ATENDIMENTO
if (event.action !== AppointmentStatusEnum.EM_ATENDIMENTO) return;
try {
// Processa atualizações em transação atômica
// ... continua no próximo passo
} catch (error) {
// Trata erros
}
}Listener atualiza médico e appointment em transação
O listener atualiza o médico como ocupado e garante o vínculo do appointment com o médico dentro de uma transação atômica:
// in-service-appointment.ts - Continuação
try {
await this.prisma.$transaction(async (tx) => {
// Marca médico como ocupado
const doctor = await tx.doctors.update({
where: {
id: event.doctorId ?? event.appointment.doctorId,
},
data: { isBusy: true },
});
// Garante vínculo do appointment com o médico
await tx.appointments.update({
where: {
id: event.appointment.id,
},
data: {
doctorId: doctor.id,
},
});
});
// Emite evento interno para propagação via WebSocket
this.eventEmitter.emit('appointments.serving', {
appointment: event.appointment,
payload: event.payload,
doctorId: event.doctorId ?? event.appointment.doctorId,
});
} catch (error) {
// Trata erros
}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.serving')
async handleAppointmentServing(data: {
appointment: AppointmentResponseDto;
payload: PayloadTokenDto;
doctorId: number;
}) {
try {
// Propaga via WebSocket para todos os clientes da conta
await this.gateway.notifyOnEvent(
'appointments.serving',
data.appointment,
data.payload,
);
this.logger.debug(
`Agendamento ${data.appointment.id} propagado via WebSocket para o medico atribuido ${data.doctorId}`,
);
} catch (error) {
this.logger.error(
`Erro ao propagar evento appointments.serving:`,
error,
);
}
}Gateway faz broadcast para todos da conta
O método `notifyOnEvent` envia o evento 'appointments.serving' 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.serving'Cliente recebe evento e remove da lista
Todos os clientes conectados da mesma conta recebem o evento 'appointments.serving' e removem o agendamento da fila de espera:
// List.tsx
socket.on('appointments.serving', (appointment: Appointment) => {
// Remove o agendamento da fila de espera
setListAppointments((prev) =>
prev.filter((apt) => apt.id !== appointment.id)
);
});
// Remove listener ao desmontar componente
useEffect(() => {
return () => {
socket.off('doctors.busy');
socket.off('appointments.checkin');
socket.off('appointments.serving');
socket.off('appointmnents.finished');
};
}, []);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-22T10:00:00.000Z",
"updatedAt": "2025-01-23T09:30:00.000Z",
"deletedAt": null,
"doctor": {
"id": 1,
"name": "Dr. Victor"
},
"patient": {
"id": 456,
"name": "João Silva",
"contact": {
"phone": "(81) 99999-9999"
}
},
"status": {
"id": 3,
"name": "Em atendimento",
"color": "#007bff"
},
"appointmentProcedures": {
"procedure": {
"id": 3699,
"name": "Ultrassom: Tireoide",
"price": "100"
}
}
}