finish.orderFinalizar Pedido
Evento WebSocket para finalizar um pedido em coleta, mudando seu status de IN_PROGRESS para COMPLETED ou CANCELED. O cliente emite este evento com o ID do pedido e o novo status desejado. O servidor valida se o pedido existe e está em IN_PROGRESS, atualiza o status no banco de dados e notifica todos os clientes conectados da mesma conta via broadcast. Este evento retorna uma resposta imediata via callback (status: 'receive' ou 'refused'), permitindo que o frontend processe o resultado instantaneamente. Em caso de sucesso, o pedido é removido da lista de "Em Progresso" e adicionado à lista de "Finalizados" (se o filtro corresponder) em 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
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
orderId | number | Sim | ID do pedido a ser finalizado |
ID do pedido a ser finalizado. É um identificador numérico único que identifica um pedido específico no sistema. Para encontrar o ID do pedido, para acessar a página de listar todos os pedidos do laboratório. | |||
status | string | Sim | Novo status do pedido. Valores possíveis: 'COMPLETED' ou 'CANCELED' |
orderIdOBRIGATÓRIOID do pedido a ser finalizado. É um identificador numérico único que identifica um pedido específico no sistema.
Para encontrar o ID do pedido, para acessar a página de listar todos os pedidos do laboratório.
statusOBRIGATÓRIOFluxo passo a passo: finish.order
Cliente emite a requisição via WebSocket com callback
O frontend emite o evento 'finish.order' com o ID do pedido e o novo status:
// FinishOrder.tsx
async function handleFinish(id: number, status: OrdersStatusEnum) {
socket?.emit(
'finish.order',
{ orderId: id, status },
(response: { status: 'receive' | 'refused'; message: string }) => {
if (response.status === 'receive') {
addNotification({
title: 'Informação',
message: `O pedido foi alterado para: ${status === OrdersStatusEnum.COMPLETED ? 'Completado' : 'Cancelado'}`,
bg: 'primary',
className: 'text-white',
autohide: true,
});
}
if (response.status === 'refused') {
addNotification({
title: 'Atenção!!!',
message: response.message,
bg: 'danger',
className: 'text-white',
autohide: true,
});
}
}
);
}Servidor valida existência e status do pedido
No backend (NestJS + Gateway), o servidor valida se o pedido existe e está em IN_PROGRESS:
@SubscribeMessage('finish.order')
async handleOrderCompleted(
@ConnectedSocket() client: Socket,
@MessageBody() data: { orderId: number; status: string },
) {
try {
const payload = client.data.payload as PayloadTokenDto;
// Busca o pedido
const exists = await this.ordersService.findById(
data.orderId,
payload,
);
// Valida se o pedido existe e está em IN_PROGRESS
if (
!exists ||
exists.status.name !== OrdersStatusEnum.IN_PROGRESS
) {
return {
status: 'refused',
message: 'O pedido não foi encontrado ou não existe',
timestamp: new Date().toISOString(),
};
}
// ... continua no próximo passo
} catch (e) {
// ... tratamento de erro
}
}Servidor valida se o status existe no banco
O servidor busca o status no banco de dados para validar se é válido:
// Continuação do handleOrderCompleted
// Busca o status no banco
const status = await this.prisma.ordersStatus.findFirst({
where: {
name: data.status, // 'COMPLETED' ou 'CANCELED'
},
});
// Valida se o status existe
if (!status) {
return {
status: 'refused',
message: 'O status não foi encontrado ou não existe',
timestamp: new Date().toISOString(),
};
}
// ... continua no próximo passoServidor emite evento interno e notifica clientes
O servidor emite evento interno para processar a atualização e notifica os clientes:
// Continuação do handleOrderCompleted
// Emite evento interno para processar a atualização
this.eventEmitter.emitAsync(
'orders.finish',
new OrderFinishEvent(
exists.id,
status.name as OrdersStatusEnum.COMPLETED | OrdersStatusEnum.CANCELED,
payload,
),
);
// Remove da lista de progresso (notifica todos os clientes)
this.handleRemoveProgress(client, exists);
// Notifica via completed (ainda com status antigo, será atualizado pelo listener)
this.notifyOnEvent('completed', exists, payload);
// Retorna sucesso
return {
status: 'receive',
timestamp: new Date().toISOString(),
};Listener atualiza pedido no banco de dados
O listener escuta o evento interno e atualiza o status do pedido no banco:
// finish.listener.ts
@OnEvent('orders.finish')
async handleOrderFinish(orderFinishEvent: OrderFinishEvent) {
try {
// Busca o status no banco
const status = await this.prisma.ordersStatus.findUnique({
where: {
name: orderFinishEvent.status, // COMPLETED ou CANCELED
},
});
// Atualiza o pedido no banco (muda de IN_PROGRESS para COMPLETED ou CANCELED)
await this.ordersService.finish(
{ id: orderFinishEvent.orderId, statusId: status.id },
orderFinishEvent.payload,
);
// Emite evento adicional para notificar com pedido atualizado
this.eventEmitter.emitAsync(
'send.orders',
new SendOrderEvent(
'completed',
orderFinishEvent.orderId,
orderFinishEvent.payload,
),
);
} catch (e) {
this.logger.debug(e);
}
}Listener notifica com pedido atualizado
O listener escuta o evento 'send.orders' e notifica todos os clientes com o pedido atualizado:
// orders.listener.ts
@OnEvent('send.orders')
async handleOnOrdersByCollect(sendEvent: SendOrderEvent) {
// Busca o pedido atualizado (com novo status)
const order = await this.ordersService.findById(
sendEvent.order,
sendEvent.payload,
);
// Notifica todos os clientes com o pedido atualizado
await this.gateway.notifyOnEvent(
sendEvent.event, // 'completed'
order,
sendEvent.payload,
);
}Clientes removem pedido da lista 'Em Progresso'
Todos os clientes conectados da mesma conta recebem o evento 'remove.progress' e removem o pedido:
// ListInProgress.tsx
socket.on('remove.progress', (remove: Order) => {
setOrders((prev) =>
prev.filter((order) => order.id !== remove.id)
);
});Clientes adicionam pedido à lista 'Finalizados'
Todos os clientes conectados da mesma conta recebem o evento 'completed' e adicionam o pedido (se o filtro corresponder):
// Side.tsx
const handleCompleted = (newOrder: Order) => {
// Filtra por status antes de adicionar
if (newOrder.status.name === searchParams.status) {
setOrders((prev) =>
// Previne duplicatas
prev.some((o) => o.id === newOrder.id)
? prev
// Adiciona no início da lista (pedidos mais recentes primeiro)
: [newOrder, ...prev]
);
}
};
socket.on('completed', handleCompleted);Request URL
ws://api-dev.imagemais.com{
"orderId": 123,
"status": "COMPLETED"
...{
"orderId": 123,
"status": "COMPLETED"
}Respostas
{
"status": "receive",
"timestamp": "2025-01-23T10:30:00.000Z"
...{
"status": "receive",
"timestamp": "2025-01-23T10:30:00.000Z"
}{
"status": "refused",
"message": "O pedido não foi encontrado ou não existe",
...{
"status": "refused",
"message": "O pedido não foi encontrado ou não existe",
"timestamp": "2025-01-23T10:30:00.000Z"
}