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
- 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.
- Configure cada ferramenta com a sua série e confira o próximo número em cada uma antes de usar.
- No emissor manual, escreva o número do pedido nas informações complementares da nota, num formato fixo, como "Pedido 10432".
- Exporte os XMLs autorizados do emissor manual e importe no sistema, que liga cada nota ao pedido pela informação complementar.
- 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.
- Liste as notas que não acharam pedido e trate uma a uma.
- 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?
Referência: https://arquivei.com.br/blog/guia-do-emissor-gratuito-de-notas-fiscais-eletronicas/