get.labelBuscar Etiquetas do Pedido
Evento WebSocket para buscar etiquetas de um pedido completado via integração SOAP com a API externa DiagnosticsBrazil. O cliente emite este evento com o ID do pedido. O servidor valida se o pedido está COMPLETED, consulta a API externa via SOAP e retorna as etiquetas formatadas. Este evento retorna uma resposta imediata via callback (status: 'receive' ou 'refused') com os dados das etiquetas e possíveis erros de integração. O frontend valida se a resposta corresponde ao pedido correto antes de processar. Este evento pode ser chamado manualmente (ao clicar em "Etiqueta") ou automaticamente quando um pedido é completado (via evento 'completed').
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 para buscar as etiquetas |
ID do pedido para operações relacionadas às etiquetas. É 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. | |||
orderIdOBRIGATÓRIOID do pedido para operações relacionadas às etiquetas. É 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.
Fluxo passo a passo: get.label
Cliente emite a requisição via WebSocket com callback
O frontend emite o evento 'get.label' com o ID do pedido e gerencia o estado de loading:
// Label.tsx
async function getLabel() {
setIsLoading(true);
socket?.emit(
'get.label',
{ orderId: order.id },
(response: LabelResponseWs) => {
// Valida se a resposta corresponde ao pedido correto
if (response.orderId !== order.id) return;
// Atualiza estado com as etiquetas
setLabels(response.data);
setIsLoading(false);
// Exibe erros se houver
if (response.errors?.length > 0) {
addNotification({
title: 'Atenção!!!',
message: response.errors
?.map((error) => error.description)
.join('|'),
bg: 'danger',
className: 'text-white',
autohide: true,
});
}
}
);
}Servidor emite evento interno e aguarda processamento
No backend (NestJS + Gateway), o servidor emite evento interno usando emitAsync para aguardar resposta dos listeners:
@SubscribeMessage('get.label')
async handleGetLabel(
@ConnectedSocket() client: Socket,
@MessageBody() data: { orderId: number },
) {
try {
// Emite evento interno e aguarda resposta (retorna array de promessas)
const promises: {
data: Record<string, any>[];
errors: Error[];
}[] = await this.eventEmitter.emitAsync(
'get.label',
new LabelEvent(data.orderId, client.data.payload),
);
// Processa primeira resposta (normalmente há apenas um listener)
const response = promises.shift();
// Retorna resposta formatada
return {
status: 'receive',
orderId: data.orderId,
data: response.data,
errors: response.errors,
timestamp: new Date().toISOString(),
};
} catch (e) {
// ... tratamento de erro
}
}Listener busca pedido e valida status
O listener escuta o evento interno, busca o pedido e valida se está COMPLETED:
// integration.listener.ts
@OnEvent('get.label')
async handleOnLabelByOrderId(labelEvent: LabelEvent) {
try {
// Chama serviço SOAP para buscar etiquetas
const confirm = await this.soapService.getLabels(
labelEvent.orderId,
labelEvent.payload,
);
return confirm; // Retorna { data: [...], errors: [...] }
} catch (e) {
const error = e as Error;
this.logger.debug(error.message, error.stack);
return {
errors: [e], // Retorna erros no formato esperado
};
}
}Serviço SOAP busca pedido, valida status e consulta API externa
O serviço SOAP busca o pedido, valida se está COMPLETED e consulta a API externa DiagnosticsBrazil:
// soap-diagnostics-brazil.service.ts
async getLabels(id: number, payload: PayloadTokenDto) {
// Busca o pedido completo
const order = await this.ordersService.findById(id, payload);
// Valida se o pedido está COMPLETED (só busca etiquetas de pedidos finalizados)
this.checkOrderStatus(order, OrdersStatusEnum.COMPLETED);
// Consulta API externa via SOAP
const [response] = await this.diagnosticsBrazilWrapper.getLabels({
request: {
CodigoApoiado: this.appConfigService.dbLogin,
CodigoSenhaIntegracao: this.appConfigService.dbPassword,
NumeroAtendimentoApoiado: `${order.patientExams.prefix}-${order.patientExams.uuid}`,
},
});
// Formata resposta da API externa
const result = response.EnviaAmostrasResult as EnviaAmostrasResult;
return this.formatConfirm(
result.Confirmacao,
order.patientExams.patient.dateBirth,
);
}Serviço formata resposta com etiquetas e erros
O método formatConfirm formata os dados retornados pela API externa em estrutura interna:
// soap-diagnostics-brazil.service.ts
private formatConfirm(confirm: Confirmacao, dateBirth: Date | string) {
return {
// Array de etiquetas formatadas
data: confirm.ConfirmacaoPedidov2.ct_ConfirmacaoPedidoEtiqueta_v2.flatMap(
(obj) =>
obj.Amostras
? obj.Amostras.ct_AmostraEtiqueta_v2.map((label) => ({
numeroAmostra: label.NumeroAmostra,
nomePaciente: label.NomePaciente,
exames: label.Exames,
grupoInterface: label.GrupoInterface,
material: label.Material,
volume: label.Volume,
meioColeta: label.MeioColeta,
regiaoColeta: label.RegiaoColeta,
origem: label.Origem,
dataNascimento: dateBirth,
dataSistema: label.DataSistema,
numeroAtendimento: obj.NumeroAtendimentoDB,
}))
: [],
),
// Array de erros de integração
errors: confirm.ConfirmacaoPedidov2.ct_ConfirmacaoPedidoEtiqueta_v2.flatMap(
(error) =>
error.ErroIntegracao
? error.ErroIntegracao.ct_ErroIntegracao_v2.map((e) => ({
description: e.Descricao,
}))
: [],
),
};
}Servidor retorna resposta formatada ao cliente
O Gateway processa a resposta do listener e retorna ao cliente via callback:
// Continuação do handleGetLabel
// Processa primeira resposta (normalmente há apenas um listener)
const response = promises.shift();
// Retorna resposta formatada
return {
status: 'receive',
orderId: data.orderId, // Para validação no frontend
data: response.data, // Array de etiquetas formatadas
errors: response.errors, // Array de erros (se houver)
timestamp: new Date().toISOString(),
};Cliente valida resposta e atualiza estado
No frontend, o callback valida se a resposta corresponde ao pedido correto e atualiza o estado:
// Label.tsx - Callback do socket.emit
(response: LabelResponseWs) => {
// Valida se a resposta corresponde ao pedido correto
if (response.orderId !== order.id) return;
// Atualiza estado com as etiquetas
setLabels(response.data);
setIsLoading(false);
// Exibe erros se houver
if (response.errors?.length > 0) {
addNotification({
title: 'Atenção!!!',
message: response.errors
?.map((error) => error.description)
.join('|'),
bg: 'danger',
className: 'text-white',
autohide: true,
});
}
}Cliente escuta evento 'completed' e busca etiquetas automaticamente
O componente escuta o evento 'completed' e busca etiquetas automaticamente se as condições forem atendidas:
// Label.tsx
socket.on('completed', (completed: Order) => {
// Só busca se estiver aguardando impressão
if (!isWindowPrint.current) return;
// Valida condições antes de buscar
if (
order.id !== completed.id || // Deve ser o mesmo pedido
labels.length !== 0 || // Não deve ter etiquetas já carregadas
completed.status.name !== OrdersStatusEnum.COMPLETED // Status deve ser COMPLETED
) return;
// Busca etiquetas automaticamente
getLabel();
});Request URL
ws://api-dev.imagemais.com{
"orderId": 123
}{
"orderId": 123
}Respostas
{
"status": "receive",
"orderId": 123,
...{
"status": "receive",
"orderId": 123,
"data": [
{
"numeroAmostra": "12345",
"nomePaciente": "João Silva",
"exames": "Hemograma Completo",
"grupoInterface": "LAB",
"material": "Sangue",
"volume": "5ml",
"meioColeta": "Tubo EDTA",
"regiaoColeta": "Braço direito",
"origem": "Coleta domiciliar",
"dataNascimento": "1990-01-01",
"dataSistema": "2025-01-23T10:30:00.000Z",
"numeroAtendimento": "DB123456"
}
],
"errors": [],
"timestamp": "2025-01-23T10:30:00.000Z"
}{
"status": "refused",
"message": "Erro ao buscar etiquetas",
...{
"status": "refused",
"message": "Erro ao buscar etiquetas",
"timestamp": "2025-01-23T10:30:00.000Z"
}