reports.completeLaudos Criados Automaticamente
Evento WebSocket para notificar em tempo real quando laudos são criados automaticamente após um pedido ser finalizado. Este evento é emitido automaticamente pelo servidor após criar laudos para procedimentos que requerem laudo local (laudoLocal: true), 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 recarreguem suas listas de laudos pendentes 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 pedido é finalizado com status COMPLETED e contém procedimentos que precisam de laudo local, o servidor cria automaticamente os laudos e emite este evento para notificar todos os clientes.
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: reports.complete
Cliente finaliza pedido e servidor emite evento interno
Quando um pedido é finalizado via WebSocket 'finish.order', o servidor valida e emite evento interno:
// accounts.gateways.ts
@SubscribeMessage('finish.order')
async handleOrderCompleted(
@ConnectedSocket() client: Socket,
@MessageBody() data: { orderId: number; status: string },
) {
// ... valida order e status ...
// Emite evento interno após validar
this.eventEmitter.emitAsync(
'orders.finish',
new OrderFinishEvent(
exists.id,
status.name as OrdersStatusEnum.COMPLETED | OrdersStatusEnum.CANCELED,
payload,
),
);
// Notifica order completado imediatamente
this.notifyOnEvent('completed', exists, payload);
return { status: 'receive', timestamp: new Date().toISOString() };
}Listener cria laudos automaticamente e emite evento
O order-finish.listener.ts escuta o evento interno, cria laudos para procedimentos que precisam e emite evento:
// order-finish.listener.ts
@OnEvent('orders.finish')
async handleOrderFinish(orderFinishEvent: OrderFinishEvent) {
// Só processa se order foi completado (não cancelado)
if (orderFinishEvent.status !== OrdersStatusEnum.COMPLETED) return;
try {
await this.prisma.$transaction(async (tx) => {
// Busca order com procedimentos que têm laudoLocal: true
const order = await tx.orders.findUnique({
where: { id: orderFinishEvent.orderId },
select: {
ulid: true,
budgets: {
select: {
budgetsProcedures: {
where: {
procedure: { laudoLocal: true }, // Apenas procedimentos com laudo local
},
// ...
},
},
},
},
});
// Se não há procedimentos que precisam de laudo, retorna
if (order.budgets[0].budgetsProcedures.length === 0) return;
// Cria laudos para cada procedimento (paralelo)
await Promise.all(
order.budgets[0].budgetsProcedures.map(async (budgetProcedure) => {
// Verifica se laudo já existe (evita duplicatas)
const exists = await this.reportsService.exists(
orderFinishEvent.payload,
{ orderUlid: order.ulid, procedureId: budgetProcedure.procedure.id },
);
if (exists.data) return; // Pula se já existe
// Cria novo laudo
await this.reportsService.create(
orderFinishEvent.payload,
{ orderUlid: order.ulid, procedureId: budgetProcedure.procedure.id },
);
}),
);
// Emite evento após criar todos os laudos
this.gateways.notifyOnEvent(
'reports.complete',
{}, // Objeto vazio (apenas notifica que laudos foram criados)
orderFinishEvent.payload,
);
});
} catch (e) {
this.logger.error(e);
}
}Gateway faz broadcast para todos da conta
O método `notifyOnEvent` envia o evento 'reports.complete' 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: 'reports.complete' (está na lista de eventos permitidos - linha 111)
// Dados: objeto vazio {} (apenas notifica que laudos foram criados)
// Todos os clientes conectados da mesma accountId recebem o eventoCliente recebe evento e recarrega lista de laudos
O componente ReportIcon.tsx escuta o evento e recarrega a lista de laudos pendentes:
// ReportIcon.tsx
async function loadReports() {
const { status, data, message } = await reports();
if (status) {
setOrders(data || []); // Atualiza lista de orders com laudos pendentes
}
if (!status) {
setError(message || 'Erro ao buscar laudos');
}
}
useEffect(() => {
if (!socket) return;
// Carrega lista inicial ao montar
loadReports();
// Escuta evento e recarrega lista quando laudos são criados
socket.on('reports.complete', () => {
loadReports(); // Recarrega lista de laudos pendentes
});
return () => {
socket.off('reports.complete');
};
}, [socket]);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
{}{}