Skip to content

Commit

Permalink
#4 - Criado retorno para a operação NfeConsultaProtocolo. Ajustado bu…
Browse files Browse the repository at this point in the history
…ilder das respostas e unificado semelhanças no Base
  • Loading branch information
Brunomm committed Jan 5, 2017
1 parent 7476bf3 commit d0efdd7
Show file tree
Hide file tree
Showing 27 changed files with 1,457 additions and 153 deletions.
3 changes: 3 additions & 0 deletions lib/br_nfe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,14 @@ module Response
autoload :Base
autoload :NfeAutorizacao
autoload :NfeRetAutorizacao
autoload :NfeConsultaProtocolo
autoload :Event
module Build
extend ActiveSupport::Autoload
autoload :Base
autoload :NfeAutorizacao
autoload :NfeRetAutorizacao
autoload :NfeConsultaProtocolo
end
end
end
Expand Down
8 changes: 7 additions & 1 deletion lib/br_nfe/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ module Constants
NFE_STATUS_SUCCESS = %w[100 101 102 103 104 107 111 112 124 128 135 138 139 140 150 151]
NFE_STATUS_PROCESSING = %w[105]
NFE_STATUS_OFFLINE = %w[108 109]
NFE_STATUS_DENIED = %w[110 301 302 303 999]
NFE_STATUS_DENIED = %w[110 205 301 302 303]

NFE_SITUATION_AUTORIZED = %w[100 124 139 140 150]
NFE_SITUATION_ADJUSTED = %w[128 135 136]
NFE_SITUATION_CANCELED = %w[101 151 218]
NFE_SITUATION_DENIED = %w[110 205 301 302 303]
NFE_SITUATION_DRAFT = %w[105 106 108 109 137 142]


end
Expand Down
36 changes: 35 additions & 1 deletion lib/br_nfe/product/nota_fiscal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,9 @@ def processed_at
alias_attribute :dhRecbto, :processed_at

# STATUS DA OPERAÇÃO
# Esse é o status final de toda a operação.
# Esse é o status final da operação com anota fiscal.
# A partir do status é possível identificar se obteve sucesso
# no processamento da nota (para qualquer operação)
#
attr_accessor :status_code
attr_accessor :status_motive
Expand All @@ -999,6 +1001,38 @@ def status
end
end

# SITUAÇÃO DA NOTA FISCAL
# Informa o status atual da nota fiscal.
# Retorna se a nota fiscal está autorizada, cancelada, denegada, rejeitada, ajustada.
# Exemplo:
# - :autorized - Quando a nota fiscal está autorizada para uso
# - :adjusted - Quando a nota fiscal está autorizada para o uso e foi realizado algum
# evento posterior que a mesma foi ajustada
# - :draft - Quando a nota fiscal ainda não tem validade fiscal.
# - :canceled - Quando a nota fiscal foi cancelada.
# - :denied - Quando a nota fiscal foi denegada e o XML deve ser guardado.
# - :rejected - Quando a nota fiscal foi rejeitada e pode ser enviada novamente com as correções.
#
attr_accessor :situation
def situation
@situation ||= get_situation_by_status_code
end
def get_situation_by_status_code
if "#{status_code}".strip.in?( BrNfe::Constants::NFE_SITUATION_AUTORIZED )
:autorized
elsif "#{status_code}".strip.in?( BrNfe::Constants::NFE_SITUATION_ADJUSTED )
:adjusted
elsif "#{status_code}".strip.in?( BrNfe::Constants::NFE_SITUATION_CANCELED )
:canceled
elsif "#{status_code}".strip.in?( BrNfe::Constants::NFE_SITUATION_DENIED )
:denied
elsif status_code.blank? || "#{status_code}".strip.in?( BrNfe::Constants::NFE_SITUATION_DRAFT )
:draft
else
:rejected
end
end

def default_values
{
versao_aplicativo: 0,
Expand Down
4 changes: 4 additions & 0 deletions lib/br_nfe/product/operation/nfe_consulta_protocolo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def ssl_version
def xml_builder
@xml_builder ||= render_xml 'root/NfeConsultaProtocolo'
end

def response_class_builder
BrNfe::Product::Response::Build::NfeConsultaProtocolo
end
end
end
end
Expand Down
141 changes: 141 additions & 0 deletions lib/br_nfe/product/response/build/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ def response_xml
@response_xml ||= parse_nokogiri_xml(savon_response.try(:xml))
end

# XMLNS PADRÃO DA NOTA FISCAL
#
def nf_xmlns
'http://www.portalfiscal.inf.br/nfe'
end

private

# Reponsável por converter uma string(XML) em um elemento
Expand All @@ -139,6 +145,141 @@ def parse_nokogiri_xml str_xml
Nokogiri::XML('<?xml version="1.0" encoding="UTF-8"?>'+str_xml)
end
end

# Rsponsável por instânciar uma nota fiscal a partir da tag protNFe.
# Também vai setar o atributo xml específico da nota fiscal a partir
# do valor setado em :original_xml
#
# Deve ser passado por parâmetro um objeto da class Nokogiri::XML::Document
# com a estrutura do protocolo da NFE. EX:
# <protNFe versao="3.10">
# <infProt>
# <tpAmb>2</tpAmb>
# <verAplic>SVRS201611281548</verAplic>
# <chNFe>42161208897094000155550010000000031201601010</chNFe>
# <dhRecbto>2016-12-23T15:02:01-02:00</dhRecbto>
# <nProt>342160000820227</nProt>
# <digVal>eoBzPod21zF9/46jjOS2kLRyTPM=</digVal>
# <cStat>100</cStat>
# <xMotivo>Autorizado o uso da NF-e</xMotivo>
# </infProt>
# </protNFe>
#
# <b>Type: </b> _BrNfe.nota_fiscal_product_class_
#
def build_invoice_by_prot_nfe prot_nfe
invoice = BrNfe.nota_fiscal_product_class.new do |nfe|
nfe.processed_at = get_processed_at_from_prot_nfe( prot_nfe )
nfe.protocol = get_protocol_from_prot_nfe( prot_nfe )
nfe.digest_value = get_digest_value_from_prot_nfe( prot_nfe )
nfe.status_code = get_status_code_from_prot_nfe( prot_nfe )
nfe.status_motive = get_status_motive_from_prot_nfe( prot_nfe )
nfe.chave_de_acesso = get_access_key_from_prot_nfe( prot_nfe )
end
# 1° - Seta os valores possíveis encontrados na chave de acesso da NF-e
set_invoice_values_by_access_key!( invoice )

# 2° - Seta o XML da respectiva NF-e no objeto já com a tag <nfeProc>
# e a tag do protocolo(<protNFe>)
set_invoice_xml_with_prot_nfe!( invoice, prot_nfe )
invoice
end

def get_processed_at_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/dhRecbto').text
end
def get_protocol_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/nProt').text
end
def get_digest_value_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/digVal').text
end
def get_status_code_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/cStat').text
end
def get_status_motive_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/xMotivo').text
end
def get_access_key_from_prot_nfe prot_nfe
prot_nfe.xpath('//protNFe/infProt/chNFe').text
end

# Seta os valores que estão concatenados na chave da NF-e
# como o número da nota fiscal, cnpj do emitente, entre outros
# valores.
#
def set_invoice_values_by_access_key!(invoice)
if invoice.chave_de_acesso.present?
invoice.emitente.cnpj = invoice.chave_de_acesso[6..19]
invoice.modelo_nf = invoice.chave_de_acesso[20..21]
invoice.serie = invoice.chave_de_acesso[22..24]
invoice.numero_nf = invoice.chave_de_acesso[25..33].to_i
invoice.codigo_nf = invoice.chave_de_acesso[35..42].to_i
end
end

# Responsável por adicionar a tag <protNFe> dentro da tag <nfeProc>.
# Também irá setar o XMl atualizado no attr :xml da nota fiscal
#
def set_invoice_xml_with_prot_nfe!(invoice, prot_nfe)
if nfeProc = find_or_create_nfeProc_of_invoice_xml_by_access_key( invoice )
# Só adiciona o protocolo se a nota foi emitida com sucesso
if invoice.status == :success
add_prot_nfe_into_nfe_proc( nfeProc, prot_nfe )
end

invoice.xml = '<?xml version="1.0" encoding="UTF-8"?>'+canonicalize( nfeProc.to_xml )
end
end

# Responsável por adicionar o protocolo da NFe dentro da tag nfeProc
# a baixo da tag NFe.
# Caso já exista a tag protNFe não irá adiciona-lo novamente.
#
def add_prot_nfe_into_nfe_proc nfe_proc, prot_nfe
if nfe_proc.xpath('//nf:nfeProc/nf:protNFe', nf: nf_xmlns).blank?
nfe_proc.xpath('//nf:nfeProc', nf: nf_xmlns).
children.last.try(:add_next_sibling, prot_nfe.root.to_xml )
end
end

# Responsável por Encontrar ou Criar a estrutura nfeProc de uma
# Determinada nota fiscal.
# 1° Verifica se existe algum XML setado no objeto da nota, e se existir,
# irá montar a nfeProc da nota e retornar o documento XML
# 2° Caso não encontre o xml direto na NF, irá procurar o xml através
# do método original_xml.
#
# Estrutura de retorno:
# <nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
# <NFe>...</NFe>
# </nfeProc>
#
# <b>Type: </b> _Nokogiri::XML::Document_
#
def find_or_create_nfeProc_of_invoice_xml_by_access_key invoice
doc_nf = "#{invoice.xml}".strip.present? ? parse_nokogiri_xml("#{invoice.xml}") : parse_nokogiri_xml(original_xml)
if node = doc_nf.search("NFe/infNFe[@Id*=\"#{invoice.chave_de_acesso}\"]").first
if doc_nf.xpath('/*').first.try(:name) == 'nfeProc'
doc_nf
else
parse_nokogiri_xml( create_proc_tag( node.parent.to_s ) )
end
end
end

# Responsável por criar a tag <nfeProc> e adicionar o conteúdo
# passado por parâmetro dentro da tag.
# Deve ser passado o xml em forma de String.
#
# <b>Type: </b> _String_
#
def create_proc_tag nfe_xml
xml = "<nfeProc xmlns=\"#{nf_xmlns}\" versao=\"#{xml_version_str}\">"
xml << nfe_xml
xml << '</nfeProc>'
xml
end
end
end
end
Expand Down
43 changes: 10 additions & 33 deletions lib/br_nfe/product/response/build/nfe_autorizacao.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module BrNfe
module Product
module Response
module Build
class NfeAutorizacao < NfeRetAutorizacao
class NfeAutorizacao < Base

def notas_fiscais
operation.notas_fiscais
Expand All @@ -24,8 +24,8 @@ def response_class
#
def specific_attributes
attrs = {
environment: body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:tpAmb', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text,
app_version: body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:verAplic', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text,
environment: body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:tpAmb', nf: nf_xmlns, ret: url_xmlns_retorno).text,
app_version: body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:verAplic', nf: nf_xmlns, ret: url_xmlns_retorno).text,
processed_at: request_processed_at,

processing_status_code: get_processing_status_code,
Expand All @@ -35,9 +35,9 @@ def specific_attributes
if async_protocol.present?
# Se entrar aqui é porque o lote é assíncrono e tem um protocolo
attrs[:protocol] = async_protocol
attrs[:tempo_medio] = body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:infRec/nf:tMed', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
attrs[:tempo_medio] = body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:infRec/nf:tMed', nf: nf_xmlns, ret: url_xmlns_retorno).text
else
attrs[:protocol] = body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:protNFe/nf:infProt/nf:nProt', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
attrs[:protocol] = body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:protNFe/nf:infProt/nf:nProt', nf: nf_xmlns, ret: url_xmlns_retorno).text
end

manage_invoices!
Expand All @@ -47,11 +47,11 @@ def specific_attributes
end

def async_protocol
@async_protocol ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:infRec/nf:nRec', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
@async_protocol ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:infRec/nf:nRec', nf: nf_xmlns, ret: url_xmlns_retorno).text
end

def node_prot_nfe
body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:protNFe', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno)
body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:protNFe', nf: nf_xmlns, ret: url_xmlns_retorno)
end

def manage_invoices!
Expand Down Expand Up @@ -86,37 +86,14 @@ def set_invoice_protocol! invoice, prot_nfe
private

def request_processed_at
@request_processed_at ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:dhRecbto', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
@request_processed_at ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:dhRecbto', nf: nf_xmlns, ret: url_xmlns_retorno).text
end

def get_processing_status_code
@get_processing_status_code ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:cStat', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
@get_processing_status_code ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:cStat', nf: nf_xmlns, ret: url_xmlns_retorno).text
end
def get_processing_status_motive
@get_processing_status_motive ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:xMotivo', nf: "http://www.portalfiscal.inf.br/nfe", ret: url_xmlns_retorno).text
end

# Responsável montar o XML da tag <nfeProc>, aplicar o XMl da nfe
# dentro e adicionar o protocolo.
#
# Primeiro irá verificar se existe algum XML setado na própria NF-e
# e se tiver, irá utilizar esse XML para criar a estrutura da <nfeProc>.
# Caso a NF-e não tenha o XML, irá buscar o XML da nfe através do atributo
# :original_xml.
#
# <b>Type: </b> _Nokogiri::XML::Document_
#
def find_invoice_xml_by_access_key invoice
doc_nf = parse_nokogiri_xml("#{invoice.xml}")
if node = doc_nf.search("NFe/infNFe[@Id*=\"#{invoice.chave_de_acesso}\"]").first
if doc_nf.xpath('/*').first.try(:name) == 'nfeProc'
doc_nf
else
parse_nokogiri_xml( create_proc_tag( node.parent.to_s ) )
end
else
super
end
@get_processing_status_motive ||= body_xml.xpath('//ret:nfeAutorizacaoLoteResult/nf:retEnviNFe/nf:xMotivo', nf: nf_xmlns, ret: url_xmlns_retorno).text
end
end
end
Expand Down
Loading

0 comments on commit d0efdd7

Please sign in to comment.