Pular para o conteúdo principal

Compartilhamento de Documentos de Nota Fiscal

Esta funcionalidade permite aos usuários baixar e compartilhar arquivos XML e PDF de notas fiscais diretamente pelo aplicativo móvel, facilitando o envio de documentos fiscais para contadores, clientes ou outros sistemas.

Visão Geral

O sistema de compartilhamento de documentos integra-se aos fluxos existentes de visualização de vendas e pedidos, oferecendo duas opções principais nos menus de ações:

  • "IMPRIMIR NOTA FISCAL" - Para compartilhamento de PDF (DANFE)
  • "COMPARTILHAR NF (XML)" - Para compartilhamento de XML

Características Principais

  • 📄 Múltiplos formatos - XML e PDF (DANFE)
  • 📱 Compartilhamento nativo através do sistema operacional
  • 🔐 Autenticação segura usando credenciais em cache
  • 📊 Feedback visual com toast messages
  • 🔄 Integração múltipla em diversos componentes
  • 🎯 Modal de seleção para PDFs com opções customizáveis

Onde Encontrar

A funcionalidade está disponível nos seguintes locais:

LocalizaçãoComponenteContexto
Componente CS Ordercs-order.tsxVisualização de pedidos
Preview de Pedidosorder-preview.navigator.tsxNavegação de preview
Detalhes de Vendassales-details.screen.tsxTela de detalhes completos
Card de Vendassales-card.tsxLista de vendas

Como Usar

Para o Usuário Final

Compartilhamento XML

  1. Acesse qualquer tela com informações de vendas/pedidos
  2. Toque no menu de ações (geralmente representado por três pontos)
  3. Selecione a opção "COMPARTILHAR NF (XML)"
  4. Aguarde o processamento (toast de carregamento aparecerá)
  5. Escolha o aplicativo de destino no menu de compartilhamento nativo

Compartilhamento PDF (DANFE)

  1. Acesse qualquer tela com informações de vendas/pedidos
  2. Toque no menu de ações ou no botão de compartilhar
  3. Selecione "IMPRIMIR NOTA FISCAL" (ou "GERAR CÓPIA DA NOTA FISCAL" para Junco)
  4. Aguarde a pré-visualização do PDF
  5. Toque no ícone de compartilhar , no canto superior direito
  6. Aguarde o processamento e compartilhe

Implementação Técnica

Serviço XML

O serviço de XML está localizado em src/services/get-sale-xml.service.ts:

import RNFS from "react-native-fs";
import { axios } from "./api";
import { CacheService } from "./cache.service";
import Share from "react-native-share";
import Toast from "react-native-toast-message";

export const getSaleXML = async ({
NUNOTANF,
}: {
NUNOTANF: string | number;
}) => {
try {
const cache = await CacheService.getAuthCache();
if (!cache)
throw new Error("Não foi possível gerar o XML: credenciais inválidas");

const response = await axios.get(`/ppid/${NUNOTANF}/viewXML`, {
responseType: "arraybuffer",
auth: {
username: cache.user,
password: cache.password,
},
});

const xmlData = response?.data;
if (!xmlData || xmlData.byteLength === 0) {
throw new Error("Não foi possível gerar o XML: resposta vazia");
}

return xmlData;
} catch (error) {
console.error("Erro ao baixar XML:", error);
throw error;
}
};

Função de Compartilhamento

export const handleDownloadXML = async ({
NUNOTANF,
}: {
NUNOTANF: string | number;
}) => {
try {
// Exibe toast de carregamento
Toast.show({
type: "info",
text1: "Aguarde...",
text2: "Gerando arquivo XML para compartilhamento",
autoHide: false,
});

const xmlData = await getSaleXML({ NUNOTANF });
const fileName = `venda-${NUNOTANF}.xml`;
const path = `${RNFS.DocumentDirectoryPath}/${fileName}`;

await RNFS.writeFile(path, Buffer.from(xmlData).toString(), "utf8");

await Share.open({
url: `file://${path}`,
type: "application/xml",
filename: fileName,
});

Toast.hide();
Toast.show({
type: "success",
text1: "Sucesso",
text2: "Arquivo XML compartilhado!",
visibilityTime: 2000,
});
} catch (error) {
Toast.hide();
Toast.show({
type: "error",
text1: "Erro ao compartilhar XML",
text2: "Tente novamente",
visibilityTime: 3000,
});
console.log("Erro ao compartilhar XML:", error);
}
};

Serviço PDF

O serviço de PDF está localizado em src/services/pdf.service.ts no namespace PDFService:

export async function getDanfeCookieAndHeaders(
credentials,
danfeNuNota,
useToken
) {
try {
let bearer = "";
if (useToken) {
const res = await getToken(credentials);
if (res.status == 200) {
bearer = res.data.data.Token;
bearer = bearer.replace(/^Bearer\s/, "");
}
}

let cookie = await api.getDanfeCookie(credentials);
cookie = cookie.data.responseBody.jsessionid.$;
let res = await getDanfeHeaders(cookie, danfeNuNota, bearer);

const dataToSend = {
reqStatus: res,
cookie: cookie,
isDanfe: true,
danfeNuNota: danfeNuNota,
};

if (bearer.length > 0) {
dataToSend.bearer = bearer;
}

return dataToSend;
} catch (e) {
Toast.show({
type: "error",
text1: "Erro",
text2: "Erro ao Consultar ERP",
autoHide: true,
onPress: () => Toast.hide(),
});
throw new Error(e.message);
}
}

Componente de Compartilhamento PDF

O componente OrderPDFShare (src/components/cs-order/order-pdf-share/order-pdf-share.tsx) gerencia a interface de seleção e compartilhamento de PDFs:

interface OrderPDFShareProps {
danfeData?: any;
visible: boolean;
onBackdropPress: () => void;
onSelect: (currentPdfData: any, index: any) => Promise<void>;
boletoData: CompanyPedidoPDF[];
reportData: CompanyPedidoPDF[];
saleId: string;
isOffline: boolean;
}

Integração nos Componentes

Para integrar as funcionalidades em um novo componente:

XML

import { handleDownloadXML } from "../../services/get-sale-xml.service";

// 1. Adicione a opção no menu de dados
data.push({
DESCRICAO: "COMPARTILHAR NF (XML)",
DANFE: sale.NUNOTANF,
});

// 2. Adicione a verificação condicional no handler
if (currentPdfData.DESCRICAO.includes("XML")) {
await handleDownloadXML({ NUNOTANF: currentPdfData.DANFE });
return;
}

PDF

import { PDFService } from "../../services/pdf.service";
import SelectReportPdfModal from "./selectReportPdfModal";
import { OrderPDFShare } from "./order-pdf-share/order-pdf-share";

// 1. Adicione a opção no menu de dados
data.push({
DESCRICAO: isJunco ? "GERAR CÓPIA DA NOTA FISCAL" : "IMPRIMIR NOTA FISCAL",
DANFE: sale.NUNOTANF.toString(),
});

// 2. No handler, processe PDF normalmente
if (currentPdfData.DANFE) {
try {
pdfReqBody = await PDFService.getDanfeCookieAndHeaders(
credentials,
mergedPdfData[index].DANFE,
UTILAPIGATEWAY === "S"
);
// Abrir modal de seleção ou processar diretamente
} catch (error) {
// Tratamento de erro
}
}

Dependências

Para XML

  • react-native-fs: Para manipulação de arquivos no sistema
  • react-native-share: Para compartilhamento nativo
  • react-native-toast-message: Para feedback visual

Para PDF

  • @ui-kitten/components: Para componentes de interface (Modal, Select, etc.)
  • react-native-toast-message: Para feedback visual
  • PDFService: Serviço interno para processamento de PDFs
  • OrderPDFShare: Componente para seleção de opções de PDF

Estados e Feedback

Toast Messages

TipoTítuloDescriçãoDuração
info"Aguarde...""Gerando arquivo XML para compartilhamento"Infinito
success"Sucesso""Arquivo XML compartilhado!"2 segundos
error"Erro ao compartilhar XML""Tente novamente"3 segundos

Tratamento de Erros

O sistema trata os seguintes cenários de erro:

  1. Credenciais inválidas: Cache de autenticação não encontrado
  2. Resposta vazia: API retorna dados vazios ou inválidos
  3. Erro de rede: Problemas de conectividade
  4. Erro de sistema: Problemas com arquivos ou compartilhamento

API Endpoints

GET /ppid/:NUNOTANF/viewXML

Endpoint responsável por retornar o arquivo XML da nota fiscal.

Parâmetros

  • NUNOTANF (path): Número da nota fiscal

Headers

  • Authorization: Basic Auth usando credenciais em cache

Response

  • Content-Type: application/xml
  • Body: ArrayBuffer contendo dados XML

PDF Endpoints

POST /getDanfeCookie

Obtém cookie de sessão para autenticação de PDFs.

POST /getDanfeHeaders

Obtém headers necessários para geração de DANFE.

GET /getToken

Obtém token Bearer quando UTILAPIGATEWAY === 'S'.

Parâmetros PDF

  • credentials: Credenciais de autenticação
  • danfeNuNota: Número da nota fiscal
  • useToken: Boolean indicando se deve usar token Bearer

Troubleshooting

Problemas Comuns

XML

  1. "Credenciais inválidas"

    • Causa: Cache de autenticação expirado ou corrompido
    • Solução: Solicitar que o usuário faça login novamente
  2. "Resposta vazia"

    • Causa: Nota fiscal não possui XML disponível ou erro no servidor
    • Solução: Verificar se a nota fiscal foi processada corretamente
  3. Menu de compartilhamento não abre

    • Causa: Problemas com a biblioteca react-native-share
    • Solução: Verificar se as permissões estão configuradas no Android/iOS

PDF

  1. "Erro ao Consultar ERP"

    • Causa: Problemas na comunicação com o servidor ERP
    • Solução: Verificar conectividade e credenciais
  2. Modal não abre

    • Causa: Problemas nos dados ou estado do componente
    • Solução: Verificar se reportSelectData está populado
  3. PDF não é gerado

    • Causa: Problemas com cookies, headers ou token
    • Solução: Verificar logs do PDFService e configurações do gateway

Debugging

XML

console.log("NUNOTANF:", NUNOTANF);
console.log("XML Data length:", xmlData?.byteLength);
console.log("File path:", path);

PDF

console.log("PDF Request Body:", pdfReqBody);
console.log("Merged PDF Data:", mergedPdfData);
console.log("Use Token:", UTILAPIGATEWAY === "S");
console.log("Current PDF Data:", currentPdfData);

Melhorias Futuras

Possíveis Evoluções

XML

  • Cache de XMLs: Armazenar XMLs baixados para evitar downloads repetidos
  • Visualização prévia: Permitir visualizar o conteúdo XML antes do compartilhamento

Otimizações Técnicas

  • Background processing: Processamento em background para melhor UX
  • Retry automático: Tentativas automáticas em caso de falha
  • Progress indicator: Indicador de progresso para downloads grandes

Changelog

VersãoDataAlterações
1.0.02024-01-XXImplementação inicial da funcionalidade

Última atualização: 10/10/2025 Responsável: Denis L M Cravo