inovadora_xml 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d085759f5ffcfeabf39f9d77bf68e3e65e927c99802cb1b517ad96ee2f6a01a8
4
- data.tar.gz: 4432bb36fd14c314becaf64dab92c1dbc4568278444e92cde823fca3d2dcbeaf
3
+ metadata.gz: ad13d1d25c4701914abef86f01658c92389afd78bff13f083d05c9837c414014
4
+ data.tar.gz: db01f6d4256b679ba6b0aa196c339a2dd2316de06a648c42f700f36c7358abc9
5
5
  SHA512:
6
- metadata.gz: '0902f045d8a90b477b72c7c92e22b8772270dceeddbaab191c6c725ba80473d9df804e1b3d6328e2a6a8542779ef27945ff479087af889feb72ae4c792da2b39'
7
- data.tar.gz: 8c47daa7d44244c15d34cfe6b5ffde1175d24fafb434e9b412f59a125f30b3d7f0138791f7f70834bc532c10ba8a383894889a7796a9ccb64ba1e2e6e4d62363
6
+ metadata.gz: 3299357a42af7a8ac44bac322e5585ff84655a44313af5e9d43c883889af4b9d3f94c79fda5eedc8f9a0caf6725a8ecade429dfb0ae63f8651fb9c4e087a6ca9
7
+ data.tar.gz: a36581b84ad314bb3b80c6f107628fcf2bf0baaab27f84035a4feda52875225b95bba7b8298f86930123ae6a46e8e56b86c26dee2f81d7a8d6a13c512728cddc
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # InovadoraXml
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/inovadora_xml`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'inovadora_xml'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install inovadora_xml
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/inovadora_xml. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the InovadoraXml project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/inovadora_xml/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,97 @@
1
+ #encoding: utf-8
2
+ require 'action_pack'
3
+
4
+ require "inovadora_xml/version"
5
+
6
+ require "inovadora_xml/assinador"
7
+ require "inovadora_xml/servidor_wsdl"
8
+
9
+
10
+ module InovadoraXml
11
+ extend ActiveSupport::Autoload
12
+ attr_accessor :xml_nfse, :schema, :metodo_soap, :xml_gerado, :retorno, :wsdl, :cert, :key, :errors
13
+ autoload :Modules
14
+ autoload :CustomExceptions
15
+
16
+ class Xml
17
+ attr_accessor :xml_nfse, :schema, :metodo_soap, :xml_gerado, :retorno, :wsdl, :cert, :key, :errors
18
+
19
+ include InovadoraXml::Modules::FormatadorNfse
20
+ include InovadoraXml::Modules::GeradorXml
21
+
22
+ def initialize(*args)
23
+ self.errors = ActiveModel::Errors.new(self)
24
+ self.xml_gerado = self.gerar_xml()
25
+
26
+ self.validar_args()
27
+ # self.valid?
28
+ end
29
+
30
+ def comunicar(request_args = {})
31
+ if self.valid?
32
+ servidor = InovadoraXml::ServidorWsdl.new(
33
+ self.envelopar(),
34
+ self.metodo_soap,
35
+ self.wsdl,
36
+ self.cert,
37
+ self.key,
38
+ request_args
39
+ )
40
+
41
+ unless servidor.enviar
42
+ raise InovadoraXml::CustomExceptions::ServerError.new(servidor), "Server Error"
43
+ end
44
+ #usage: self.retorno.to_xml ou self.retorno.body
45
+ self.retorno = servidor.retorno
46
+ end
47
+
48
+ rescue InovadoraXml::CustomExceptions::ServerError => e
49
+ e.object.errors.full_messages.each {|e| "Erro na comunicação: #{self.errors.add(:base, e)}"}
50
+ rescue Exception => e
51
+ self.errors.add(:base, e.message)
52
+ ensure
53
+ return self.errors.blank?
54
+ end
55
+
56
+ def validar_args
57
+ self.errors.add(:base, "Metodo SOAP não especificado") if self.metodo_soap.blank?
58
+ self.errors.add(:base, "Schema não especificado") if self.schema.blank?
59
+ self.errors.add(:base, "WSDL não especificado") if self.wsdl.blank?
60
+
61
+ return self.errors.blank?
62
+ end
63
+
64
+ def valid?
65
+ erros = []
66
+ schema = open(self.schema)
67
+ xsd = Nokogiri::XML::Schema(schema)
68
+ xsd.validate(self.xml_gerado).each do |error|
69
+ unless error.message.to_s.include?("{http://www.w3.org/2000/09/xmldsig#}Signature") ||
70
+ error.message.to_s.include?("{http://www.w3.org/2000/09/xmldsig#}SignedInfo")
71
+ erros << "(Linha: " + error.line.to_s + ") => " + error.message.to_s
72
+ end
73
+ end
74
+
75
+ erros.each {|erro| self.errors.add(:base, erro)}
76
+ rescue Errno::ENOENT => e
77
+ self.errors.add(:base, "Arquivo schema não existe")
78
+ rescue Exception => e
79
+ self.errors.add(:base, e)
80
+ ensure
81
+ self.errors.blank?
82
+ end
83
+
84
+ def assinar(tag_assinar)
85
+ assinador = InovadoraXml::Assinador.new(self.xml_gerado, tag_assinar, self.cert, self.key)
86
+ assinador.assinar_xml
87
+
88
+ assinador.errors.full_messages.each do |error|
89
+ self.errors.add(:base, error)
90
+ end
91
+
92
+ self.xml_gerado = assinador.xml_assinado if assinador.errors.blank?
93
+ ensure
94
+ return self.errors.blank?
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,122 @@
1
+ #encoding=utf-8
2
+ module InovadoraXml
3
+ class Assinador
4
+ attr_accessor :xml_assinar, :xml_assinado, :tag_assinar, :cert, :key, :errors, :parametro
5
+
6
+ def initialize(xml, tag_assinar, cert, key)
7
+ self.errors = ActiveModel::Errors.new(self)
8
+
9
+ self.xml_assinar = xml.to_s
10
+ self.tag_assinar = tag_assinar
11
+ self.cert = cert
12
+ self.key = key
13
+ end
14
+
15
+ def assinar_xml()
16
+ if self.valid?
17
+ chave_privada = OpenSSL::PKey::RSA.new(File.read(self.key))
18
+ certificado = OpenSSL::X509::Certificate.new(File.read(self.cert))
19
+
20
+ self.xml_assinado = Nokogiri::XML(self.xml_assinar.to_s, &:noblanks)
21
+ self.xml_assinado.xpath("//xmlns:#{self.tag_assinar}").each do |node|
22
+
23
+ # 1. Digest Hash for all XML
24
+ xml_canon = node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
25
+ xml_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(xml_canon)).strip
26
+
27
+ # 2. Add Signature Node
28
+ signature = Nokogiri::XML::Node.new('Signature', self.xml_assinado)
29
+ signature.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
30
+ node.after(signature)
31
+
32
+ # 3.1 Create Signature Info
33
+ signature_info = Nokogiri::XML::Node.new('SignedInfo', self.xml_assinado)
34
+
35
+ # 3.2 Add CanonicalizationMethod
36
+ child_node = Nokogiri::XML::Node.new('CanonicalizationMethod', self.xml_assinado)
37
+ child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
38
+ signature_info.add_child child_node
39
+
40
+ # 3.3 Add SignatureMethod
41
+ child_node = Nokogiri::XML::Node.new('SignatureMethod', self.xml_assinado)
42
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
43
+ signature_info.add_child child_node
44
+
45
+ # 3.4 Create Reference
46
+ reference = Nokogiri::XML::Node.new('Reference', self.xml_assinado)
47
+ reference['URI'] = "##{node.first.last}"
48
+
49
+ # 3.5 Add Transforms
50
+ transforms = Nokogiri::XML::Node.new('Transforms', self.xml_assinado)
51
+
52
+ child_node = Nokogiri::XML::Node.new('Transform', self.xml_assinado)
53
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
54
+ transforms.add_child child_node
55
+
56
+ child_node = Nokogiri::XML::Node.new('Transform', self.xml_assinado)
57
+ child_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
58
+ transforms.add_child child_node
59
+
60
+ reference.add_child transforms
61
+
62
+ # 3.6 Add Digest
63
+ child_node = Nokogiri::XML::Node.new('DigestMethod', self.xml_assinado)
64
+ child_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#sha1'
65
+ reference.add_child child_node
66
+
67
+ # 3.6 Add DigestValue
68
+ child_node = Nokogiri::XML::Node.new('DigestValue', self.xml_assinado)
69
+ child_node.content = xml_digest
70
+ reference.add_child child_node
71
+
72
+ # 3.7 Add Reference and Signature Info
73
+ signature_info.add_child reference
74
+ signature.add_child signature_info
75
+
76
+ # 4 Sign Signature
77
+ sign_canon = signature_info.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
78
+ signature_hash = chave_privada.sign(OpenSSL::Digest::SHA1.new, sign_canon)
79
+ signature_value = Base64.encode64(signature_hash).gsub("\n", '')
80
+
81
+ # 4.1 Add SignatureValue
82
+ child_node = Nokogiri::XML::Node.new('SignatureValue', self.xml_assinado)
83
+ child_node.content = signature_value
84
+ signature.add_child child_node
85
+
86
+ # 5 Create KeyInfo
87
+ key_info = Nokogiri::XML::Node.new('KeyInfo', self.xml_assinado)
88
+
89
+ # 5.1 Add X509 Data and Certificate
90
+ x509_data = Nokogiri::XML::Node.new('X509Data', self.xml_assinado)
91
+ x509_certificate = Nokogiri::XML::Node.new('X509Certificate', self.xml_assinado)
92
+ x509_certificate.content = certificado.to_s.gsub(/\-\-\-\-\-[A-Z]+ CERTIFICATE\-\-\-\-\-/, "").gsub(/\n/,"")
93
+
94
+ x509_data.add_child x509_certificate
95
+ key_info.add_child x509_data
96
+
97
+ # 5.2 Add KeyInfo
98
+ signature.add_child key_info
99
+ end
100
+
101
+ # Return XML
102
+ self.xml_assinado.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
103
+ end
104
+ rescue Exception => e
105
+ self.errors.add(:base, e.message)
106
+ ensure
107
+ return self.errors.blank?
108
+ end
109
+
110
+ def valid?
111
+ self.errors.add(:base, "Chave não informada" ) unless self.key.present?
112
+ self.errors.add(:base, "Certificado não informado" ) unless self.cert.present?
113
+ self.errors.add(:base, "Arquivo chave não encontrado") unless File.exists?(self.key.to_s)
114
+ self.errors.add(:base, "Arquivo certificado não encontrado") unless File.exists?(self.cert.to_s)
115
+
116
+ rescue Exception => e
117
+ self.errors.add(:base, e.message)
118
+ ensure
119
+ return self.errors.blank?
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,6 @@
1
+ module InovadoraXml
2
+ module CustomExceptions
3
+ # extend ActiveSupport::Autoload
4
+ autoload :ServerError, "inovadora_xml/custom_exceptions/server_error"
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ module InovadoraXml
2
+ module CustomExceptions
3
+ class ServerError < StandardError
4
+ attr_reader :object
5
+
6
+ def initialize(object)
7
+ @object = object
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module InovadoraXml
2
+ module Modules
3
+ # extend ActiveSupport::Autoload
4
+ autoload :FormatadorNfse, "inovadora_xml/modules/formatador_nfse"
5
+ autoload :GeradorXml, "inovadora_xml/modules/gerador_xml"
6
+ autoload :DadosNfseService, "inovadora_xml/modules/dados_nfse_service"
7
+ autoload :XmlRetorno, "inovadora_xml/modules/xml_retorno"
8
+ end
9
+ end
@@ -0,0 +1,143 @@
1
+ # encoding=utf-8
2
+ module InovadoraXml
3
+ module Modules
4
+ module DadosNfseService
5
+ def get_numero_lote_rps
6
+ self.fnnfse.build_fnnfses_sancionada if self.fnnfse.fnnfses_sancionada.blank?
7
+ (self.fnnfse.fnnfses_sancionada.numero_rps = self.fnnfse.class.connection.select_value("SELECT nextval('gestho.prox_nro_rps_nfse')")) if self.fnnfse.fnnfses_sancionada.numero_rps.to_s == ""
8
+
9
+ self.fnnfse.fnnfses_sancionada.numero_lote_rps = self.fnnfse.class.connection.select_value("SELECT nextval('gestho.prox_nro_lote_rps_nfse')")
10
+ self.fnnfse.fnnfses_sancionada.save
11
+ return self.fnnfse.fnnfses_sancionada.numero_lote_rps
12
+ end
13
+
14
+ def get_itens_servicos
15
+ case self.parametro.fornecedor
16
+ when 7..8 # Publica e #NF-em
17
+ get_itens_servicos_publica
18
+ else
19
+ "Não implementado para esse fornecedor"
20
+ end
21
+ end
22
+
23
+ def get_itens_servicos_publica
24
+ itens_da_nota= "{"
25
+ if self.fnnfse.descritivo_servico.to_s == ""
26
+ unless self.fnnfse.fnpacote.nil?
27
+ itens_da_nota += "[" +
28
+ "[Descricao=#{self.fnnfse.try(:fnpacote).try(:descricao)} #{fnnfse.obs_pacote}]" +
29
+ "[Quantidade=1.0]" +
30
+ "[ValorUnitario=#{self.fnnfse.valor_pacote}]" +
31
+ "[Deducoes=0]" +
32
+ "[DescontoCondicionado=0]" +
33
+ "[DescontoIncondicionado=#{self.fnnfse.valor_pacote_desconto.to_f.round(2)}]" +
34
+ "[Aliquota=#{get_aliquota}]" +
35
+ "[itemServico=#{get_item_lista_servico}]" +
36
+ "]"
37
+ end
38
+ self.fnnfse.fnnfseis.each do |fnnfsei|
39
+ qtde = fnnfsei.qtde.to_f.round(2) == 0 ? 1.0 : fnnfsei.qtde.to_f.round(2)
40
+ itens_da_nota += "[" +
41
+ "[Descricao=#{fnnfsei.ftforma.nome}]" +
42
+ "[Quantidade=#{qtde}]" +
43
+ "[ValorUnitario=#{(fnnfsei.valor.to_f / qtde).round(8)}]" +
44
+ "[Deducoes=0]" +
45
+ "[DescontoCondicionado=0]" +
46
+ "[DescontoIncondicionado=#{fnnfsei.desconto.to_s.to_d}]" +
47
+ "[Aliquota=#{get_aliquota}]" +
48
+ "[itemServico=#{get_item_lista_servico}]" +
49
+ "]"
50
+ end
51
+ else
52
+ itens_da_nota += "[" +
53
+ "[Descricao=#{self.fnnfse.descritivo_servico}]" +
54
+ "[Quantidade=1.0]" +
55
+ "[ValorUnitario=#{self.fnnfse.valor_servicos}]" +
56
+ "[Deducoes=0]" +
57
+ "[DescontoCondicionado=0]" +
58
+ "[DescontoIncondicionado=#{self.fnnfse.valor_descontos}]" +
59
+ "[Aliquota=#{get_aliquota}]" +
60
+ "[itemServico=#{get_item_lista_servico}]" +
61
+ "]"
62
+ end
63
+ itens_da_nota += "}"
64
+ end
65
+
66
+ def get_itens_servicos_texto
67
+ itens_da_nota = ""
68
+ if self.fnnfse.descritivo_servico.to_s == ""
69
+ if self.fnnfse.try(:fnpacote).present?
70
+ itens_da_nota += "#{self.fnnfse.try(:fnpacote).try(:descricao)} #{fnnfse.obs_pacote} " +
71
+ "Valor: #{self.fnnfse.valor_pacote} " +
72
+ "Desconto: #{self.fnnfse.valor_pacote_desconto.to_f.round(2)}"
73
+ end
74
+ if self.fnnfse.fnnfseis.size > 1
75
+ self.fnnfse.fnnfseis.each do |fnnfsei|
76
+ qtde = fnnfsei.qtde.to_f.round(2) == 0 ? 1.0 : fnnfsei.qtde.to_f.round(2)
77
+ itens_da_nota += "- #{fnnfsei.ftforma.nome} Qtde: #{qtde} " +
78
+ "Valor: #{((fnnfsei.valor.to_f / qtde).round(8)).round(2)} " +
79
+ (fnnfsei.desconto.to_s.to_d>0 ? "Desconto: #{fnnfsei.desconto.to_s.to_d.round(2)}" : "") +
80
+ " \n"
81
+ end
82
+ else
83
+ fnnfsei = self.fnnfse.fnnfseis.first
84
+ itens_da_nota += "#{fnnfsei.ftforma.nome}" rescue ""
85
+ end
86
+ else
87
+ itens_da_nota += "#{self.fnnfse.descritivo_servico} " +
88
+ "Valor: #{self.fnnfse.valor_servicos.to_d.round(2)} " +
89
+ (self.fnnfse.valor_descontos.to_d>0 ? "Desconto: #{self.fnnfse.valor_descontos.to_d.round(2)}" : "")
90
+ end
91
+ itens_da_nota
92
+ end
93
+
94
+ def get_informacoes_complementares
95
+ mensagem = self.fnnfse.observacao.to_s.strip
96
+ if self.fnnfse.cliente_type == "Paciente"
97
+ intern = self.fnnfse.fnnfses_interns.try(:first).try(:intern)
98
+ unless intern.blank?
99
+ mensagem += " Intern:#{intern.id}-#{intern.paciente.try(:nome).try(:strip)}"
100
+ mensagem += " Conv.:#{self.fnnfse.get_convenio.try(:nome).try(:strip)}"
101
+ mensagem += " CPF:#{intern.paciente.cpf}" if intern.paciente.cpf.to_s.strip != "" && intern.paciente.cpf.to_s.strip != "0"
102
+ mensagem += " Nasc:#{intern.paciente.data_nascimento.to_s_br}"
103
+ end
104
+ end
105
+ mensagem = nil if mensagem.to_s.strip.blank?
106
+ mensagem
107
+ end
108
+
109
+ def get_item_lista_servico
110
+ self.hospital.iss_cd_lei_116 || '4.03'
111
+ end
112
+
113
+ def get_aliquota
114
+ self.fnnfse.percentual_iss || 0.0
115
+ end
116
+
117
+ def get_cnpj_prestador
118
+ self.hospital.cgc.to_s.gsub(/[^0-9]/, "")
119
+ end
120
+
121
+ def get_inscricao_municipal_prestador
122
+ self.hospital.inscricao_municipal.to_s.gsub(/[^0-9]-/, "")
123
+ end
124
+
125
+ def get_codigo_municipio_prest_servico
126
+ self.hospital.cidade_ibge.try(:ibge_com_digito)
127
+ end
128
+
129
+ def persistir_fnnfses_xml(xml, tipo_documento = 17)
130
+ xml_tratado = Nokogiri::XML(CGI.unescapeHTML(xml.to_xml.to_s), &:noblanks)
131
+ xml_tratado = xml_tratado.to_xml(indent: 2).to_s
132
+ if xml_tratado.blank?
133
+ xml_tratado = "xml não recebido da prefeitura"
134
+ end
135
+ # $b = {fnnfse: self.fnnfse, xml_envio: self.xml_gerado().to_s, xml_retorno: xml_tratado, errors: self.errors, tipo_documento: tipo_documento}
136
+
137
+ retorno_service = InovadoraXml::Modules::XmlRetorno.new(fnnfse: self.fnnfse, xml_envio: self.xml_gerado().to_s, xml_retorno: xml_tratado, errors: self.errors, tipo_documento: tipo_documento)
138
+
139
+ retorno_service.save
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,36 @@
1
+ #encoding: utf-8
2
+ module InovadoraXml
3
+ module Modules
4
+ module FormatadorNfse
5
+ def data_formato_br(data)
6
+ # Padrão: 11/11/2011
7
+ data = data.to_time if data.class == String
8
+ data.strftime('%d/%m/%Y') unless data.nil? || data.to_s == ""
9
+ end
10
+
11
+ def data_nfse(data)
12
+ # Padrão: 2010-11-11
13
+ data = data.to_time if data.class == String
14
+ data.strftime('%Y-%m-%d') unless data.nil? || data.to_s == ""
15
+ end
16
+
17
+ def data_hora_nfse(data)
18
+ # Padrão: 2010-09-16T14:50:00
19
+ data = data.to_time if data.class == String
20
+ data.strftime('%Y-%m-%dT%H:%M:%S') unless data.nil?
21
+ end
22
+
23
+ def data_hora_gmt(data)
24
+ # Padrão: 2010-09-16T14:50:00
25
+ data = data.to_time if data.class == String
26
+ data.strftime('%Y-%m-%dT%H:%M:%S%:z') unless data.nil?
27
+ end
28
+
29
+ def hora_nfse(data)
30
+ # Padrão: 11:26:00
31
+ data = data.to_time if data.class == String
32
+ data.strftime('%H:%M:%S') unless data.nil?
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ #encoding: utf-8
2
+ module InovadoraXml
3
+ module Modules
4
+ module GeradorXml
5
+
6
+ def elemento(elemento, valor = nil)
7
+ if valor.class == String
8
+ valor.strip!
9
+ valor = I18n.transliterate(valor)
10
+ regex = /[^a-zA-Z0-9,.\-_\/:\[\]\=\$\@\{\}\/\n ]/
11
+ #regex = /[^a-zA-Z0-9,.\-_\/:\[\]\=\$\@\{\}\/ ]/
12
+ valor = valor.gsub(regex, "")
13
+ end
14
+ self.xml_nfse.send(elemento, valor) {
15
+ yield if block_given?
16
+ } unless valor.nil?
17
+ end
18
+
19
+ def grupo(elemento, id = nil)
20
+ if id.present?
21
+ self.xml_nfse.send(elemento, id) {
22
+ yield if block_given?
23
+ }
24
+ else
25
+ self.xml_nfse.send(elemento) {
26
+ yield if block_given?
27
+ }
28
+ end
29
+ end
30
+
31
+ def construir(elemento_raiz)
32
+ builder = Nokogiri::XML::Builder.new() do |xml|
33
+ self.xml_nfse = xml
34
+ elemento(elemento_raiz, get_namespace) {
35
+ yield
36
+ }
37
+ end
38
+ xml_builder = builder.to_xml(indent: 2, encoding: "UTF-8")
39
+ doc = Nokogiri::XML(xml_builder, &:noblanks)
40
+ return doc
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,105 @@
1
+ #encoding=utf-8
2
+ module InovadoraXml
3
+ module Modules
4
+ class XmlRetorno
5
+ extend ActiveModel::Naming # Requer dependencias para uso do ActiveModel::Errors
6
+ attr_accessor :errors, :fnnfse, :fnnfses_xml, :numero_nota, :link_nota, :protocolo_prefeitura,
7
+ :codigo_verificacao_nfse, :datahora_aprovacao,
8
+ :cancelada, :data_hora_cancelamento
9
+
10
+ def initialize args={}
11
+ self.errors = args[:errors] || ActiveModel::Errors.new(self)
12
+ self.fnnfse = args[:fnnfse]
13
+ validar_dados_iniciais(args)
14
+ persistir_fnnfses_xml(args)
15
+ end
16
+
17
+ def validar_dados_iniciais(args)
18
+ if self.fnnfse.nil?
19
+ self.errors.add(:base, "NFSe não encontrada")
20
+ end
21
+ if args.blank? || args[:xml_envio].blank?
22
+ self.errors.add(:base, "XML para envio está em branco")
23
+ end
24
+ if args.blank? || args[:xml_retorno].blank?
25
+ self.errors.add(:base, "XML de retorno está em branco")
26
+ end
27
+ end
28
+
29
+ def valid?
30
+ self.errors.blank?
31
+ end
32
+
33
+ def retornou_dados_nota?
34
+ self.errors.add(:base, "Número da nota não encontrado no XML de retorno da prefeitura") if self.numero_nota.blank?
35
+ # self.errors.add(:base, "Link da nota não encontrado no XML de retorno da prefeitura") if self.link_nota.blank?
36
+ self.errors.add(:base, "Código verificação da nota não encontrado no XML de retorno da prefeitura") if self.codigo_verificacao_nfse.blank?
37
+ self.errors.add(:base, "Data aprovação da nota não encontrado no XML de retorno da prefeitura") if self.datahora_aprovacao.blank?
38
+ self.valid?
39
+ end
40
+
41
+ def save
42
+ if retornou_dados_nota?
43
+ if self.valid?
44
+ self.fnnfse.nao_validar_nota_autenticada = true
45
+ self.fnnfse.fnnfses_sancionada.numero_nota = self.numero_nota
46
+ self.fnnfse.fnnfses_sancionada.link_nota = self.link_nota
47
+ self.fnnfse.fnnfses_sancionada.codigo_verificacao_nfse = self.codigo_verificacao_nfse
48
+ self.fnnfse.fnnfses_sancionada.datahora_aprovacao = self.datahora_aprovacao
49
+ self.fnnfse.fnnfses_sancionada.protocolo_prefeitura = self.protocolo_prefeitura
50
+ self.fnnfse.save
51
+ end
52
+ if self.cancelada && self.data_hora_cancelamento.present?
53
+ self.fnnfse.reload
54
+ fnnfses_sancionada = self.fnnfse.fnnfses_sancionada
55
+ fnnfses_sancionada.cancelada = true
56
+ fnnfses_sancionada.motivo_cancelamento = fnnfses_sancionada.motivo_cancelamento.to_s + " Data/Hora cancelamento: #{self.data_hora_cancelamento.to_s_br}"
57
+ fnnfses_sancionada.save
58
+ end
59
+ end
60
+ end
61
+
62
+ def get_texto_errors
63
+ texto_errors = '<erros>\n'
64
+ texto_errors += "<erro>XML apresentou erros na geração e transmissão para o webservice</erro>\n"
65
+ if self.errors.present?
66
+ self.errors.full_messages.each do |msg|
67
+ texto_errors += "<erro>#{msg}</erro>\n"
68
+ end
69
+ end
70
+ texto_errors += '</erros>\n'
71
+ texto_errors
72
+ end
73
+
74
+ def persistir_fnnfses_xml(args)
75
+ xml_resposta_ws = (args[:xml_retorno] rescue get_texto_errors)
76
+ if xml_resposta_ws.blank?
77
+ xml_resposta_ws = get_texto_errors
78
+ end
79
+ self.fnnfses_xml = FnnfsesXml.create(
80
+ fnnfse_id: self.fnnfse.id,
81
+ tipo_documento: args[:tipo_documento],
82
+ xml_envio: (args[:xml_envio] rescue get_texto_errors),
83
+ xml_resposta: xml_resposta_ws
84
+ )
85
+ if self.fnnfses_xml.try(:get_erros).present?
86
+ self.fnnfses_xml.get_erros.each do |erro|
87
+ self.errors.add(:base, "Erro retornado pela prefeitura: #{erro}")
88
+ end
89
+ end
90
+
91
+ if self.errors.blank?
92
+ self.numero_nota = self.fnnfses_xml.get_numero_nota if (self.fnnfses_xml.get_numero_nota.present?)
93
+ self.link_nota = self.fnnfses_xml.get_link_nota if (self.fnnfses_xml.get_link_nota.present?)
94
+ self.codigo_verificacao_nfse = self.fnnfses_xml.get_codigo_verificacao_nfse if (self.fnnfses_xml.get_codigo_verificacao_nfse.present?)
95
+ self.datahora_aprovacao = self.fnnfses_xml.get_data_emissao if (self.fnnfses_xml.get_data_emissao.present?)
96
+ self.protocolo_prefeitura = self.fnnfses_xml.get_protocolo_prefeitura if (self.fnnfses_xml.get_protocolo_prefeitura.present?)
97
+ if (self.fnnfses_xml.get_data_hora_cancelamento.present? rescue false)
98
+ self.cancelada = true
99
+ self.data_hora_cancelamento = self.fnnfses_xml.get_data_hora_cancelamento
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,47 @@
1
+ #encoding: utf-8
2
+ module InovadoraXml
3
+ class ServidorWsdl
4
+ attr_accessor :xml_enviar, :metodo_soap, :wsdl, :args_request, :cert, :key, :retorno, :errors
5
+
6
+ def initialize(xml_enviar, metodo_soap, wsdl, cert = nil, key = nil, args_request = {})
7
+ self.xml_enviar = xml_enviar
8
+ self.metodo_soap = metodo_soap
9
+ self.wsdl = wsdl
10
+
11
+ self.cert = cert
12
+ self.key = key
13
+
14
+ self.args_request = args_request
15
+
16
+ self.errors = ActiveModel::Errors.new(self)
17
+ end
18
+
19
+ def enviar
20
+ begin
21
+ cliente = estabelecer_cliente()
22
+
23
+ response = cliente.request(self.metodo_soap, args_request) do
24
+ soap.xml = self.xml_enviar
25
+ end
26
+ self.retorno = response
27
+ rescue Savon::SOAP::Fault => fault
28
+ self.errors.add(:base, fault.to_s)
29
+ rescue Savon::HTTP::Error => fault2
30
+ self.errors.add(:base, fault2.to_s)
31
+ rescue Exception => e
32
+ self.errors.add(:base, e.message)
33
+ ensure
34
+ return self.errors.blank?
35
+ end
36
+ end
37
+
38
+ def estabelecer_cliente
39
+ Savon::Client.new do |wsdl, http|
40
+ wsdl.document = self.wsdl
41
+ http.auth.ssl.cert_file = self.cert unless self.cert.blank?
42
+ http.auth.ssl.cert_key_file = self.key unless self.key.blank?
43
+ http.auth.ssl.verify_mode = :none
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module InovadoraXml
2
+ VERSION = "0.0.9"
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inovadora_xml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Junior Libardoni
@@ -100,7 +100,19 @@ email:
100
100
  executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
- files: []
103
+ files:
104
+ - README.md
105
+ - lib/inovadora_xml.rb
106
+ - lib/inovadora_xml/assinador.rb
107
+ - lib/inovadora_xml/custom_exceptions.rb
108
+ - lib/inovadora_xml/custom_exceptions/server_error.rb
109
+ - lib/inovadora_xml/modules.rb
110
+ - lib/inovadora_xml/modules/dados_nfse_service.rb
111
+ - lib/inovadora_xml/modules/formatador_nfse.rb
112
+ - lib/inovadora_xml/modules/gerador_xml.rb
113
+ - lib/inovadora_xml/modules/xml_retorno.rb
114
+ - lib/inovadora_xml/servidor_wsdl.rb
115
+ - lib/inovadora_xml/version.rb
104
116
  homepage:
105
117
  licenses:
106
118
  - MIT