Programação Por Equipe DevBras

Capa do artigo: Emissor gratuito de NF-e e o sistema da loja: como os dois convivem sem duplicar

Emissor gratuito de NF-e e o sistema da loja: como os dois convivem sem duplicar

Use um emissor gratuito ao lado do seu sistema sem conflito: série separada para cada um, chave gravada no pedido e uma importação que liga cada nota à venda e baixa o estoque.

A integração de nota da loja virtual ficou fora do ar numa sexta à tarde. A dona abriu um emissor gratuito, emitiu à mão as notas 1532 a 1540 na série 1 e despachou os pacotes. Na segunda, o sistema voltou, tentou emitir a nota 1532 da série 1 e recebeu rejeição por duplicidade. E o estoque das nove vendas nunca baixou. A resposta curta: dois emissores podem conviver, desde que cada um tenha a própria série e toda nota, venha de onde vier, volte para o pedido com a chave de acesso. Separe a numeração, grave a chave no pedido e importe o XML do emissor manual para o sistema.

Este guia monta essa ponte com a mesma loja, em PHP e MySQL. Ele não substitui a orientação do seu contador, que confirma série, regime e obrigações do seu caso.

Por que dois emissores viram dois mundos

Na NF-e, cada nota é identificada pelo CNPJ do emitente, o modelo, a série e o número. A Sefaz recusa um segundo documento com a mesma combinação. O emissor gratuito e o seu sistema não conversam: cada um guarda o "próximo número" no próprio banco. Se os dois usam a mesma série, cedo ou tarde os dois escolhem o mesmo número.

O segundo problema é o pedido. O emissor gratuito sabe da nota; o seu sistema sabe do pedido, do estoque, do cliente e do pagamento. Uma nota emitida fora, sem nada que a ligue de volta, não baixa estoque, não aparece no histórico do cliente e não entra no relatório de faturamento do sistema. A nota existe para a Sefaz e não existe para você.

Um detalhe de vocabulário que evita confusão: emitir por outra ferramenta quando o sistema cai não é "contingência" no sentido da NF-e. Contingência é uma modalidade prevista na regra, usada quando a autorização normal está indisponível, com marcação própria no XML. Emitir no emissor gratuito é uma emissão normal, só que por outro programa.

Como fazer os dois conviverem

  1. Combine com o contador uma série para cada emissor: por exemplo, série 1 para o sistema e série 2 para o emissor manual.
  2. Configure cada ferramenta com a sua série e confira o próximo número em cada uma antes de usar.
  3. No emissor manual, escreva o número do pedido nas informações complementares da nota, num formato fixo, como "Pedido 10432".
  4. Exporte os XMLs autorizados do emissor manual e importe no sistema, que liga cada nota ao pedido pela informação complementar.
  5. Na importação, grave chave, série, número e origem no pedido, e dispare a baixa de estoque se ela ainda não aconteceu.
  6. Liste as notas que não acharam pedido e trate uma a uma.
  7. Se algum número ficou pulado numa série, siga o procedimento de inutilização de numeração com o contador.

As colunas que o pedido precisa ter

ALTER TABLE pedido
  ADD COLUMN nfe_chave CHAR(44) NULL,
  ADD COLUMN nfe_serie SMALLINT NULL,
  ADD COLUMN nfe_numero INT NULL,
  ADD COLUMN nfe_origem VARCHAR(20) NULL,
  ADD UNIQUE KEY uq_pedido_nfe_chave (nfe_chave);

nfe_origem guarda sistema ou emissor_manual. A chave única impede ligar a mesma nota a dois pedidos. E "emitido" passa a ser um fato verificável: existe uma chave de 44 dígitos no pedido, não um checkbox marcado de memória.

A importação dos XMLs do emissor manual

<?php
function importarNotasManuais(PDO $db, string $pasta): array
{
    $semPedido = [];
    foreach (glob($pasta . '/*.xml') as $arquivo) {
        $doc = new DOMDocument();
        if (!$doc->load($arquivo)) {
            $semPedido[] = basename($arquivo) . ' (ilegível)';
            continue;
        }
        $xp = new DOMXPath($doc);
        $xp->registerNamespace('n', 'http://www.portalfiscal.inf.br/nfe');

        $status = $xp->evaluate('string(/n:nfeProc/n:protNFe/n:infProt/n:cStat)');
        if ($status !== '100') {
            $semPedido[] = basename($arquivo) . ' (não autorizada)';
            continue;
        }
        $chave  = $xp->evaluate('string(/n:nfeProc/n:protNFe/n:infProt/n:chNFe)');
        $serie  = (int) $xp->evaluate('string(/n:nfeProc/n:NFe/n:infNFe/n:ide/n:serie)');
        $numero = (int) $xp->evaluate('string(/n:nfeProc/n:NFe/n:infNFe/n:ide/n:nNF)');
        $infCpl = $xp->evaluate('string(/n:nfeProc/n:NFe/n:infNFe/n:infAdic/n:infCpl)');

        if (!preg_match('/Pedido ([0-9]+)/', $infCpl, $m)) {
            $semPedido[] = "$chave (sem número de pedido)";
            continue;
        }
        $upd = $db->prepare(
            'UPDATE pedido SET nfe_chave = ?, nfe_serie = ?, nfe_numero = ?, nfe_origem = ?
             WHERE id = ? AND nfe_chave IS NULL'
        );
        $upd->execute([$chave, $serie, $numero, 'emissor_manual', (int) $m[1]]);
        if ($upd->rowCount() === 0) {
            $semPedido[] = "$chave (pedido $m[1] inexistente ou já com nota)";
        }
    }
    return $semPedido;
}

A condição nfe_chave IS NULL torna a importação segura para rodar de novo: notas já ligadas não são regravadas. Na loja do exemplo, a importação de segunda ligou as nove notas aos pedidos e devolveu uma lista vazia. A baixa de estoque fica num passo seguinte, que procura pedidos com nota e sem movimento de saída, para não depender de a importação rodar uma única vez.

O lado do sistema

No emissor do sistema, nada muda além de a série ser só dele. Mas vale uma trava: antes de emitir, o sistema confere se o pedido já tem nfe_chave. Se tiver, não emite. Foi exatamente o que faltou na segunda-feira, quando o sistema voltou e tentou emitir notas para pedidos que já estavam faturados à mão.

Homologação e produção nunca se misturam

Teste a importação com XMLs de homologação, mas em outro banco ou com uma marcação que impeça a mistura. Nota de homologação não tem valor fiscal, e um pedido ligado a ela parece faturado sem estar. O post sobre homologação da nota que não é produção mostra como separar os ambientes. Do lado de negócio, o texto sobre emissor gratuito que não é o ERP ajuda a decidir quando a ferramenta manual deixou de bastar.

Erros comuns

  • Usar a mesma série nos dois emissores. Os dois escolhem o mesmo número e a Sefaz rejeita a nota de quem chegar depois.
  • Não escrever o pedido na nota manual. A importação não acha a venda e alguém liga as notas à mão, errando.
  • Marcar "emitido" sem chave. O pedido parece faturado, mas não há como provar qual nota é dele.
  • Emitir pelo sistema sem checar se o pedido já tem nota. A mesma venda ganha duas notas e uma precisa ser cancelada.
  • Esquecer o estoque das notas manuais. O site continua vendendo produto que já saiu.
  • Deixar número pulado sem tratar. A sequência fica com buraco que o contador precisa explicar depois.

Checklist

  • Cada emissor tem uma série própria, combinada com o contador.
  • Toda nota manual traz o número do pedido em formato fixo.
  • Os XMLs do emissor manual são importados e ligados ao pedido pela chave.
  • O pedido guarda chave, série, número e origem da nota.
  • O sistema não emite para pedido que já tem chave.
  • Notas sem pedido aparecem numa lista que alguém trata.
  • O estoque baixa para notas de qualquer origem.

Para o envio do arquivo ao cliente depois de tudo isso, veja enviar o XML da nota ao cliente. Agora escolha um pedido faturado no mês passado e tente achar a nota a partir dele, e depois o pedido a partir da nota: você consegue nos dois sentidos, para notas do sistema e do emissor manual?

Avalie este artigo

Referência: https://arquivei.com.br/blog/guia-do-emissor-gratuito-de-notas-fiscais-eletronicas/