Venda e Cancelamento

Anatomia do CF-e

O Cupom Fiscal eletrônico, CF-e, é um documento fiscal com validade jurídica que não existe fisicamente, mas apenas de forma eletrônica, em formato XML, que descreve todos os aspectos práticos de uma operação de venda ou do cancelamento de uma venda. A figura abaixo ilustra a anatomia de um CF-e de venda, destacando todos os seus elementos de mais alto nível.

Anatomia de CF-e de venda

Um documento CF-e que se compare com a ilustração, grosseiramente se traduz para o seguinte fragmento XML:

<CFe>
  <infCFe>
    <ide/>
    <emit/>
    <dest/>
    <det nItem="1">
      <prod/>
      <imposto/>
    </det>
    <total/>
    <pgto/>
  </infCFe>
  <Signature/>
</CFe>

O ponto central da tecnologia SAT-CF-e, do ponto de vista do desenvolvedor do aplicativo comercial, é o modelo através do qual um CF-e é construído até se transformar em um documento com validade jurídica.

  1. O aplicativo comercial inicia o CF-e construindo a maior parte dos elementos a partir dos dados da venda e o envia para o equipamento SAT através da função EnviarDadosVenda;
  2. O equipamento SAT complementa o CF-e, calculando e incluindo outras informações que são de sua responsabilidade e assinando digitalmente o documento, e o transmite para a SEFAZ;
  3. A SEFAZ valida o documento e o retorna para o equipamento SAT que, finalmente, retorna a resposta para o aplicativo comercial.

Para compor um CF-e o desenvolvedor do aplicativo comercial deverá observar a coluna Origem da tabela que descreve os elementos do CF-e nos itens 4.2.2 (layout do arquivo de venda) e 4.2.3 (layout do arquivo de cancelamento). Os elementos onde a coluna Origem indicar AC são os elementos que o aplicativo comercial deverá incluir no XML. Os elementos indicados com SAT são os elementos que o equipamento SAT deverá incluir.

Detalhe da coluna "Origem" indicando a origem dos elementos do CF-e

Entidades

No contexto deste projeto as Entidades são as classes que são utilizadas para descrever uma venda ou um cancelamento. A documentação da API contém uma tabela que relaciona as classes de entidades aos elementos XML descritos na ER SAT, em Módulo satcfe.entidades.

Lidar com API de entidades não é difícil. O exemplo abaixo mostra uma sessão do interpretador onde é criado uma instância de LocalEntrega totalmente inválida:

>>> from satcfe.entidades import LocalEntrega
>>> entrega = LocalEntrega()
>>> entrega.validar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "satcfe/entidades.py", line 298, in validar
    'atributos invalidos.'.format(self.__class__.__name__))
cerberus.cerberus.ValidationError: Entidade "LocalEntrega" possui atributos invalidos.
>>> entrega.erros
{'xBairro': 'required field', 'nro': 'required field', 'UF': 'required field', 'xMun': 'required field', 'xLgr': 'required field'}

Para obter o fragmento XML de uma entidade, faça:

>>> entrega = LocalEntrega(
...         xLgr='Rua Armando Gulim',
...         nro='65',
...         xBairro=u'Parque Glória III',
...         xMun='Catanduva',
...         UF='SP')
>>> entrega.documento(incluir_xml_decl=False)
'<entrega><xLgr>Rua Armando Gulim</xLgr><nro>65</nro><xBairro>Parque Gloria III</xBairro><xMun>Catanduva</xMun><UF>SP</UF></entrega>'

Criando um CF-e de Venda

Criar um CF-e de venda é simples no que diz respeito à composição dos elementos. Obviamente, no contexto da aplicação comercial, inúmeras outras complexidades se apresentam. Mas este exemplo é capaz de produzir um XML que poderá ser enviado para o equipamento SAT.

Nota

Equipamentos SAT em desenvolvimento podem requerer que os dados do emitente sejam certos dados específicos, bem como o CNPJ que identifica a software house que desenvolve a AC. Consulte a documentação técnica do fabricante do seu equipamento SAT.

from satcomum import constantes
from satcfe.entidades import Emitente
from satcfe.entidades import Destinatario
from satcfe.entidades import LocalEntrega
from satcfe.entidades import Detalhamento
from satcfe.entidades import ProdutoServico
from satcfe.entidades import Imposto
from satcfe.entidades import ICMSSN102
from satcfe.entidades import PISSN
from satcfe.entidades import COFINSSN
from satcfe.entidades import MeioPagamento

cfe = CFeVenda(
        CNPJ='08427847000169',
        signAC=constantes.ASSINATURA_AC_TESTE,
        numeroCaixa=2,
        emitente=Emitente(
                CNPJ='61099008000141',
                IE='111111111111'),
        destinatario=Destinatario(
                CPF='11122233396',
                xNome=u'João de Teste'),
        entrega=LocalEntrega(
                xLgr='Rua Armando Gulim',
                nro='65',
                xBairro=u'Parque Glória III',
                xMun='Catanduva',
                UF='SP'),
        detalhamentos=[
                Detalhamento(
                        produto=ProdutoServico(
                                cProd='123456',
                                xProd='BORRACHA STAEDTLER pvc-free',
                                CFOP='5102',
                                uCom='UN',
                                qCom=Decimal('1.0000'),
                                vUnCom=Decimal('5.75'),
                                indRegra='A'),
                        imposto=Imposto(
                                icms=ICMSSN102(Orig='2', CSOSN='500'),
                                pis=PISSN(CST='49'),
                                cofins=COFINSSN(CST='49'))),
            ],
        pagamentos=[
                MeioPagamento(
                        cMP=constantes.WA03_DINHEIRO,
                        vMP=Decimal('10.00')),
            ])

O XML produzido por este código é um documento CF-e ainda incompleto, que deverá ser enviado ao equipamento SAT pra que seja completado, assinado e transmitido para a SEFAZ. Você poderá ver um exemplo do documento XML gerado por esse código em XML do CF-e de Venda.

Ao submeter o CF-e ao equipamento SAT, a resposta será uma instância de RespostaEnviarDadosVenda e a partir dela você poderá obter o XML do CF-e-SAT assinado e autorizado, obter os dados para geração do QRCode e outras informações:

>>> resposta = cliente.enviar_dados_venda(cfe)
>>> resposta.xml()
u'<?xml version="1.0"?><CFe><infCFe Id="CFe35150761...</Signature></CFe>'

>>> resposta.qrcode()
u'35150761099008000141599000026310000100500297|20150709172317|...JI2BCucA=='

>>> resposta.valorTotalCFe
Decimal('5.75')

Dica

Em produção, o atributo signAC deverá ser uma sequência resultante da codificação em Base64 do hash SHA256 gerado a partir do CNPJ da software house e do CNPJ do estabelecimento emitente.

A documentação da função AssociarAssinatura tem mais detalhes sobre isto.

Criando um CF-e de Cancelamento

Para realizar o cancelamento de um CF-e-SAT de venda, você irá precisar da chave de acesso do documento a ser cancelado:

from satcomum import constantes
from satcfe import BibliotecaSAT
from satcfe import ClienteSATLocal
from satcfe.entidades import CFeCancelamento

chave_acesso_venda = ... # obter a chave de acesso do CF-e-SAT de venda

cfecanc = CFeCancelamento(
        chCanc=chave_acesso_venda,
        CNPJ='08427847000169',
        signAC=contantes.ASSINATURA_AC_TESTE,
        numeroCaixa=2)

cliente = ClienteSATLocal(BibliotecaSAT('/opt/fabricante/libsat.so'),
        codigo_ativacao='12345678')

resposta = cliente.cancelar_ultima_venda(cfecanc.chCanc, cfecanc)

Assim como na venda, o cancelamento irá produzir um XML ainda incompleto que será submetido ao equipamento SAT, que o irá completá-lo, assiná-lo e transmití-lo à SEFAZ. Veja um exemplo do XML do CF-e de Cancelamento e do XML do CF-e-SAT de Cancelamento.

Se algo der errado durante o cancelamento serão lançadas exceções apropriadas. Mais detalhes em Lidando com as Respostas e Lidando com Exceções.

Para obter o XML da resposta (o CF-e-SAT de cancelamento) ou os dados do QRcode, use os métodos xml() e qrcode().