Pular para o conteúdo
Matheus Prates

Hora em Goiânia: Goiânia

ENCurrículo
Voltar para os projetos

03PDV

Um caixa que não para quando a internet cai.

Venda, crediário, estoque e nota fiscal eletrônica direto na SEFAZ, com o balcão ligado ao servidor por uma VPN que eu montei.

Do técnico de impressora ao sistema que imprime a nota fiscal.

  • React
  • Express
  • Prisma
  • PostgreSQL
  • NFC-e
  • WireGuard
Balcão do PDV com três produtos no carrinho, o detalhe do item escolhido e o total de R$ 41,50
Venda registrada de R$ 41,50, com a escolha entre cupom não fiscal e nota fiscal eletrônica

O problema

Uma loja precisava vender, controlar caixa e fiado e emitir nota fiscal eletrônica num sistema só, que continuasse funcionando quando a internet cai.

O que eu construí

  • Venda com leitura de código de barras e pagamento em dinheiro, débito, crédito, PIX ou a prazo.
  • Caixa com abertura, sangria, suprimento e fechamento.
  • Crediário com juros e controle de quem deve.
  • Estoque que entra pela importação do XML da nota de compra.
  • Nota fiscal de consumidor eletrônica autorizada na SEFAZ, com certificado digital e cupom em PDF com QR Code.
  • Funciona sem internet e sincroniza quando a conexão volta.

As telas

Prints do sistema de verdade. Clique numa tela para ver em tamanho real.

  • Tela de entrada com os módulos Balcão e Gestão

    Entrada: o balcão, que vende o dia inteiro, e a gestão, ainda em construção.

  • Balcão com o aviso de produto sem NCM no cadastro

    Produto sem NCM: a venda segue, e o sistema avisa que a nota vai ser recusada até o cadastro ser corrigido.

  • Tela de pagamento com dinheiro, PIX, débito, crédito e fiado

    Pagamento em dinheiro, PIX, débito, crédito ou fiado, com o troco calculado sozinho.

  • Tela de pagamento com desconto de cinco reais aplicado

    Desconto em reais, registrado na venda e impresso no cupom.

  • Painel do caixa com abrir, fechar, sangria, suprimento, relatório do dia e sincronizar

    Caixa: abertura, sangria, suprimento, fechamento e sincronização manual.

  • Carrinho vazio com a lista de itens que saíram da venda

    Item tirado do carrinho fica registrado para conferência, sem entrar na conta.

Como funciona

  1. No balcão

    O caixa roda no navegador e guarda as vendas no próprio computador, em IndexedDB.

  2. No servidor

    A API em Express, com Prisma e PostgreSQL, recebe as vendas quando há conexão.

  3. Na SEFAZ

    A nota é assinada com o certificado da loja e enviada para autorização.

  4. O caminho

    O balcão fala com o servidor por uma VPN WireGuard só dele.

Decisões que importaram

  1. Offline primeiro

    Por quê: Caixa parado é venda perdida. O balcão continua vendendo sem internet e acerta as contas depois.

  2. Dado sensível cifrado

    Por quê: Certificado e dados de cliente ficam cifrados com AES-256-GCM no banco.

  3. VPN própria para o balcão

    Por quê: O computador da loja não fica exposto na internet: conversa com o servidor por um túnel fechado.

O que deu errado

Todo sistema de verdade quebra de algum jeito. Estes foram os tropeços que mais ensinaram, e o que mudou por causa deles.

  1. O cartão novo assinava num formato recusado

    O que aconteceu

    O certificado digital da loja venceu, e o cartão novo gerava uma assinatura que a SEFAZ não aceitava. Não havia driver corrigido publicado.

    O que mudou

    Escrevi um transmissor próprio que fala PKCS#11 direto com o cartão e assina em PKCS#1, o formato aceito. A emissão voltou.

  2. O agente estava de pé, conectado e inútil

    O que aconteceu

    O programa que assina as notas no balcão parecia saudável: o processo existia e a conexão estava aberta. Mas não assinava nada, e isso custou três dias em agosto.

    O que mudou

    O vigia agora pergunta ao próprio agente se o cartão está conectado e se a assinatura funciona, e reinicia quando não. Processo vivo não prova serviço funcionando.

  3. O zero que sumia do código fiscal

    O que aconteceu

    Na importação da nota de compra, o leitor de XML transformava o NCM 02071413 em número, e o zero da frente sumia. A SEFAZ recusava as notas desses produtos.

    O que mudou

    Dado fiscal é texto, mesmo quando parece número. E o balcão passou a avisar, na hora da venda, quando o cadastro do produto está sem o código fiscal.

Onde está hoje

Em uso todo dia na loja.