br_nfe 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -1
  3. data/README.markdown +263 -1
  4. data/br_nfe.gemspec +14 -5
  5. data/lib/br_nfe/base.rb +6 -1
  6. data/lib/br_nfe/helper/cpf_cnpj.rb +0 -5
  7. data/lib/br_nfe/helper/have_address.rb +1 -5
  8. data/lib/br_nfe/helper/have_rps.rb +7 -0
  9. data/lib/br_nfe/servico/betha/base.rb +52 -41
  10. data/lib/br_nfe/servico/betha/build_response.rb +141 -0
  11. data/lib/br_nfe/servico/betha/v1/build_response.rb +4 -102
  12. data/lib/br_nfe/servico/betha/v1/consulta_lote_rps.rb +3 -1
  13. data/lib/br_nfe/servico/betha/v1/consulta_nfs_por_rps.rb +5 -2
  14. data/lib/br_nfe/servico/betha/v1/consulta_nfse.rb +2 -1
  15. data/lib/br_nfe/servico/betha/v1/gateway.rb +66 -56
  16. data/lib/br_nfe/servico/betha/v1/recepcao_lote_rps.rb +16 -8
  17. data/lib/br_nfe/servico/betha/v2/build_response.rb +159 -0
  18. data/lib/br_nfe/servico/betha/v2/cancelamento_nfs.rb +8 -3
  19. data/lib/br_nfe/servico/betha/v2/consulta_lote_rps.rb +7 -4
  20. data/lib/br_nfe/servico/betha/v2/consulta_nfse_por_rps.rb +5 -5
  21. data/lib/br_nfe/servico/betha/v2/envio_lote_rps_sincrono.rb +7 -3
  22. data/lib/br_nfe/servico/betha/v2/gateway.rb +79 -56
  23. data/lib/br_nfe/servico/betha/v2/gera_nfse.rb +8 -3
  24. data/lib/br_nfe/servico/betha/v2/recepcao_lote_rps.rb +9 -4
  25. data/lib/br_nfe/servico/betha/v2/substituicao_nfse.rb +8 -4
  26. data/lib/br_nfe/servico/response/nota_fiscal.rb +13 -4
  27. data/lib/br_nfe/servico/rps.rb +2 -2
  28. data/lib/br_nfe/version.rb +1 -1
  29. data/lib/br_nfe.rb +2 -1
  30. data/test/br_nfe/base_test.rb +55 -1
  31. data/test/br_nfe/destinatario_test.rb +19 -0
  32. data/test/br_nfe/emitente_test.rb +20 -0
  33. data/test/br_nfe/endereco_test.rb +9 -0
  34. data/test/br_nfe/helper/cpf_cnpj_test.rb +61 -0
  35. data/test/br_nfe/servico/base_test.rb +28 -0
  36. data/test/br_nfe/servico/betha/base_test.rb +61 -32
  37. data/test/br_nfe/servico/betha/v1/build_response_test.rb +6 -7
  38. data/test/br_nfe/servico/betha/v1/cancelamento_nfs_test.rb +6 -0
  39. data/test/br_nfe/servico/betha/v1/consulta_lote_rps_test.rb +4 -0
  40. data/test/br_nfe/servico/betha/v1/consulta_nfse_test.rb +17 -0
  41. data/test/br_nfe/servico/betha/v1/gateway_test.rb +17 -40
  42. data/test/br_nfe/servico/betha/v1/recepcao_lote_rps_test.rb +12 -2
  43. data/test/br_nfe/servico/betha/v2/cancelamento_nfs_test.rb +40 -0
  44. data/test/br_nfe/servico/betha/v2/consulta_lote_rps_test.rb +38 -0
  45. data/test/br_nfe/servico/betha/v2/consulta_nfse_por_rps_test.rb +36 -0
  46. data/test/br_nfe/servico/betha/v2/envio_lote_rps_sincrono_test.rb +46 -0
  47. data/test/br_nfe/servico/betha/v2/gateway_test.rb +372 -0
  48. data/test/br_nfe/servico/betha/v2/gera_nfse_test.rb +58 -0
  49. data/test/br_nfe/servico/betha/v2/recepcao_lote_rps_test.rb +103 -0
  50. data/test/br_nfe/servico/betha/v2/substituicao_nfse_test.rb +80 -0
  51. data/test/br_nfe/servico/intermediario_test.rb +16 -0
  52. data/test/br_nfe/servico/rps_test.rb +141 -0
  53. data/test/factories/servico/betha/v1/gateway.rb +1 -1
  54. data/test/factories/servico/betha/v2/cancelamento_nfs.rb +7 -0
  55. data/test/factories/servico/betha/v2/consulta_lote_rps.rb +6 -0
  56. data/test/factories/servico/betha/v2/consulta_nfse_por_rps.rb +6 -0
  57. data/test/factories/servico/betha/v2/envio_lote_rps_sincrono.rb +5 -0
  58. data/test/factories/servico/betha/v2/gateway.rb +5 -0
  59. data/test/factories/servico/betha/v2/gera_nfse.rb +6 -0
  60. data/test/factories/servico/betha/v2/recepcao_lote_rps.rb +5 -0
  61. data/test/factories/servico/betha/v2/substituicao_nfse.rb +8 -0
  62. metadata +50 -17
  63. data/Gemfile +0 -15
  64. data/Rakefile +0 -13
  65. data/lib/br_nfe/seed.rb +0 -195
  66. data/lib/br_nfe/servico/betha/v2/response.rb +0 -23
  67. data/test/certificado.rb +0 -12
  68. data/test/test_helper.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5bff6e1698aa7f99b9173ab613f2b9de121b63e
4
- data.tar.gz: 204e49ce93ce25e694a3b6a097ba6160bdf0f65e
3
+ metadata.gz: d81e02350802d65933239ed64f4e46ac7f214e59
4
+ data.tar.gz: 4775126aada4c05183bdb6b1227575dff1df7f0e
5
5
  SHA512:
6
- metadata.gz: 06922cf1c5b2512e79f14b70a3c97410a84e683cb2ee88bc7184ffc246c84546e4ea4038396a417ff8e4dc2b45a64727905102f2273be85260cce467a3b999a7
7
- data.tar.gz: c9d88601560d5130d7d8c4d04e4226d68a050f8a98f96d7a74605a8f06e1c04609f3993805cd244274bdc14e8c6c380f5266429ae811e2154da962464556087e
6
+ metadata.gz: 93b60f03c14917b7e79724be3853e3681bc88921f0e9d7b0c98463cfe8282ba8f37858354fa4b640c17e415bcde89b8e51e21981f75d79926ff8aa99f97cabba
7
+ data.tar.gz: 2341287f4bdaf2994584db7318408b1242c45683d7038be7d72f65531b7ae888ac10f6a4b5cf3b447ac7b8c1322897a16e15328f6b7ead0e0ae877f579391823
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- br_nfe (1.0.0)
4
+ br_nfe (1.0.1)
5
5
  activemodel (~> 4.2)
6
6
  activesupport (~> 4.2)
7
7
  nokogiri (~> 1.6)
@@ -53,6 +53,8 @@ GEM
53
53
  ansi (1.5.0)
54
54
  arel (6.0.2)
55
55
  builder (3.2.2)
56
+ codeclimate-test-reporter (0.4.8)
57
+ simplecov (>= 0.7.1, < 1.0.0)
56
58
  docile (1.1.5)
57
59
  erubis (2.7.0)
58
60
  factory_girl (4.5.0)
@@ -159,6 +161,7 @@ PLATFORMS
159
161
 
160
162
  DEPENDENCIES
161
163
  br_nfe!
164
+ codeclimate-test-reporter
162
165
  factory_girl_rails
163
166
  minitest-matchers_vaccine
164
167
  minitest-rails
data/README.markdown CHANGED
@@ -1,4 +1,266 @@
1
- # **BrNFe**
1
+ [![Build Status](https://travis-ci.org/Brunomm/br_nfe.svg?branch=master)](https://travis-ci.org/Brunomm/br_nfe)
2
+ [![Test Coverage](https://codeclimate.com/github/Brunomm/br_nfe/badges/coverage.svg)](https://codeclimate.com/github/Brunomm/br_nfe/coverage)
3
+ [![Gem Version](https://badge.fury.io/rb/br_nfe.svg)](http://badge.fury.io/rb/br_nfe)
4
+ [![Dependency Status](https://gemnasium.com/Brunomm/br_nfe.svg)](https://gemnasium.com/Brunomm/br_nfe)
5
+ [![security](https://hakiri.io/github/Brunomm/br_nfe/master.svg)](https://hakiri.io/github/Brunomm/br_nfe/master)
6
+ [![Code Climate](https://codeclimate.com/github/Brunomm/br_nfe/badges/gpa.svg)](https://codeclimate.com/github/Brunomm/br_nfe)
7
+
8
+ # **BrNfe**
9
+ Gem para emissão de notas fiscais eletrônicas.
10
+
11
+ ## Versão 1.0.1
12
+ **Motivo e Objetivo**
13
+ Devido a falta de padronização dos parâmetros e a forma de envio e resposta na transmissão de Notas Fiscais de Serviços (NFS), esta gem vem com o objetivo de obter uma forma padronizada dessa tarefa, e assim, facilitando a vida de muitos desenvolvedores.
14
+
15
+ **O que essa gem faz?**
16
+
17
+ - Assina digitalmente a nota fiscal eletrônica.
18
+ - Envia os parâmetros com a formatação adequada conforme documentação de cada web service desenvolvido.
19
+ - Formata em um padrão único a resposta de cada web service.
20
+ - Valida (opcionalmente) a obrigatoriedade de cada informação a ser enviada.
21
+
22
+ ## Instalação
23
+ **Manualmente**
24
+
25
+ gem install br_nfe
26
+
27
+ **Gemfile**
28
+
29
+ gem 'br_nfe'
30
+
31
+ ## NFS-e desenvolvidas
32
+
33
+ * Betha Sistemas V 1.0
34
+ * Betha Sistemas V 2.02
35
+
36
+ ####**1 - Começando**
37
+ Foi criado várias classes para auxiliar na montagem dos dados para emissão da NF, dentre eles estão:
38
+
39
+ ```ruby
40
+ BrNfe::Endereco
41
+ BrNfe::Emitente
42
+ BrNfe::Destinatario
43
+ BrNfe::CondicaoPagamento
44
+ BrNfe::Servico::Intermediario
45
+ BrNfe::Servico::Rps
46
+ ```
47
+
48
+ A seguir um exemplo de cada objeto com valores:
49
+
50
+ **Endereço:**
51
+ ```ruby
52
+ @endereco = BrNfe::Endereco.new({
53
+ logradouro: "RUA FERNANDO MACHADO",
54
+ numero: 369,
55
+ complemento: "E",
56
+ bairro: "CENTRO",
57
+ nome_municipio: "CHAPECÓ",
58
+ codigo_municipio: 4204202,
59
+ uf: "SC",
60
+ cep: "89665-000",
61
+ # codigo_pais: 1058, <- Default
62
+ # nome_pais: 'BRASIL', <- Default
63
+ })
64
+ ```
65
+ ***
66
+ **Emitente:**
67
+ ```ruby
68
+ @emitente = BrNfe::Emitente.new({
69
+ cnpj: '11.111.111/1111-00',
70
+ inscricao_municipal: '66165-4',
71
+ razao_social: 'RAZÃO SOCIAL',
72
+ natureza_operacao: '1',
73
+ nome_fantasia: 'NOME FANTASIA',
74
+ telefone: '4933665577',
75
+ email: 'emitente@mail.com',
76
+ regime_especial_tributacao: '1',
77
+ optante_simples_nacional: true,
78
+ incentivo_fiscal: false,
79
+ endereco: @endereco
80
+ })
81
+ ```
82
+
83
+ Perceba que para definir o endereço do emitente, foi setado diretamente o objeto `@endereco`, porém, também é possível setar o objeto endereço em forma de `block` ou `hash` (isso vale para todas as classes), por exemplo:
84
+ ```ruby
85
+ # Hash
86
+ @emitente = BrNfe::Emitente.new({
87
+ cnpj: '11.111.111/1111-00',
88
+ ...
89
+ endereco: {
90
+ logradouro: "RUA FERNANDO MACHADO",
91
+ numero: 369,
92
+ complemento: "E",
93
+ ...
94
+ }
95
+ })
96
+ # Block
97
+ @emitente = BrNfe::Emitente.new do |emitente|
98
+ emitente.cnpj = '11.111.111/1111-00'
99
+ ...
100
+ emitente.endereco do |endereco|
101
+ endereco.logradouro = "RUA FERNANDO ...",
102
+ endereco.numero = 369,
103
+ endereco.complemento = "E",
104
+ ...
105
+ end
106
+ end
107
+ ```
108
+
109
+ Lembrando que por padrão, sempre que for chamar `@emitente.endereco` irá retornar um objeto da class `BrNfe::Endereco`, mesmo que não seja setado valor algum, ex:
110
+ ```ruby
111
+ @emitente = BrNfe::Emitente.new
112
+ @emitente.endereco
113
+ # => #<BrNfe::Endereco:0x000000022669a0 @codigo_pais="1058", ....>
114
+ ```
115
+ ***
116
+ **Destinatário**
117
+ ```ruby
118
+ @destinatario = BrNfe::Destinatario.new({
119
+ cpf_cnpj: "111.111.111-00",
120
+ inscricao_municipal: "",
121
+ inscricao_estadual: "",
122
+ inscricao_suframa: "",
123
+ razao_social: "NOME DA PESSOA OU EMPRESA",
124
+ nome_fantasia: "",
125
+ telefone: "3365478",
126
+ email: "destinatario@mail.com",
127
+ endereco: {
128
+ ...
129
+ }
130
+ })
131
+ ```
132
+ ***
133
+ **Condição de pagamento**
134
+ ```ruby
135
+ @condicao_pagamento = BrNfe::CondicaoPagamento.new do |cond|
136
+ cond.condicao = 'A_PRAZO' # ou 'A_VISTA'
137
+ cond.parcelas = [
138
+ {valor: 50.33, vencimento: Date.today},
139
+ {valor: '27.00', vencimento: 1.month.since}
140
+ ]
141
+ end
142
+ ```
143
+ ***
144
+ **Intermediário do serviço**
145
+ ```ruby
146
+ @intermediario = BrNfe::Servico::Intermediario.new({
147
+ cpf_cnpj: '11.111.111/0001-36',
148
+ inscricao_municipal: '3355-6',
149
+ razao_social: "INTERMEDIÁRIO DO SERVIÇO"
150
+ })
151
+ ```
152
+ ***
153
+ **RPS**
154
+ ```ruby
155
+ @rps = BrNfe::Servico::Rps.new do |rps|
156
+ rps.destinatario = { ... } # Attributos da class BrNfe::Destinatario
157
+ rps.intermediario do |intermediario|
158
+ .... # Dados da class BrNfe::Servico::Intermediario
159
+ end
160
+ rps.condicao_pagamento = BrNfe::CondicaoPagamento.new(...)
161
+
162
+ rps.numero = 5525
163
+ rps.serie = "SN"
164
+ rps.tipo = "1"
165
+ rps.data_emissao = DateTime.now
166
+ rps.status = "1"
167
+ rps.competencia = DateTime.now
168
+ rps.numero_substituicao = "5524"
169
+ rps.serie_substituicao = "SN"
170
+ rps.tipo_substituicao = "1"
171
+ rps.codigo_obra = ""
172
+ rps.codigo_art = ""
173
+ rps.valor_servicos = 100.00
174
+ rps.valor_deducoes = "0"
175
+ rps.valor_pis = "0"
176
+ rps.valor_cofins = ""
177
+ rps.valor_inss = ""
178
+ rps.valor_ir = ""
179
+ rps.valor_csll = ""
180
+ rps.outras_retencoes = ""
181
+ rps.iss_retido = ""
182
+ rps.valor_iss = 2.0
183
+ rps.aliquota = 0.02 # = 2%
184
+ rps.base_calculo = "100.00"
185
+ rps.desconto_incondicionado = ""
186
+ rps.desconto_condicionado = ""
187
+ rps.responsavel_retencao = ""
188
+ rps.item_lista_servico = "1.07"
189
+ rps.discriminacao = "1 Configuração de servidor: R$ 500.00"
190
+ rps.exigibilidade_iss = "1"
191
+ rps.codigo_municipio = "4204202"
192
+ rps.municipio_incidencia = "4204202"
193
+ rps.codigo_pais = ""
194
+ rps.numero_processo = ""
195
+ rps.codigo_cnae = ""
196
+ rps.outras_informacoes = ""
197
+ rps.codigo_tributacao_municipio = ""
198
+ end
199
+ ```
200
+ ####**2 - Exemplos**
201
+ Para todos os Web Services, após instanciados, poderá ser chamado o método `request`, no qual será enviado os dados via XML para o órgão emissor correspondente.
202
+
203
+ Se desejar, antes de enviar os dados, o objeto poderá ser validado, EX:
204
+ ```ruby
205
+ @ws = BrNfe::Servico::Betha::V1::ConsultaLoteRps.new(...)
206
+ if @ws.valid?
207
+ @ws.request
208
+ @response = @ws.response
209
+ end
210
+ ```
211
+ O resultado obtido na variável `@response` é um objeto da class `BrNfe::Servico::Response::Default`, no qual será retornada em todas as requisições. Essa classe é responsável de manter o padrão das mensagens de resposta para todos os webservices. Se desejar, poderá obter a resposta original (no formato Hash) de cada órgão emissor através do método `original_response`.
212
+ Para saber quais os valores obtidos pelo `BrNfe::Servico::Response::Default`, veja: [Resposta padrão](exemplos/resposta_padrao.markdown)
213
+
214
+ Lista de exemplos:
215
+
216
+ * [Betha Sistemas v1.0](exemplos/betha_v1.markdown)
217
+ * [Betha Sistemas v2.02](exemplos/betha_v2.markdown)
218
+
219
+ ####**3 - Configurações**
220
+ ```ruby
221
+ BrNfe.setup do |config|
222
+ # É possível customizar as classes auxiliares, por exemlo,
223
+ # se você quiser fazer alguma validação específica para o endereço,
224
+ # que contenha os mesmo atributos, e setar na configuração da gem
225
+ # qual será a classe que irá representar o endereco.
226
+ # config.endereco_class = ClasseCustomizadaEndereco
227
+
228
+ config.endereco_class = BrNfe::Endereco
229
+ config.emitente_class = BrNfe::Emitente
230
+ config.destinatario_class = BrNfe::Destinatario
231
+ config.intermediario_class = BrNfe::Servico::Intermediario
232
+ config.condicao_pagamento_class = BrNfe::CondicaoPagamento
233
+ config.rps_class BrNfe::Servico::Rps
234
+
235
+ # Se você utiliza certificado SSL, faça as seguintes modificações na configuração:
236
+ # config.client_wsdl_ssl_verify_mode = :peer
237
+ # config.client_wsdl_ssl_cert_file = 'caminho/client_cert.pem'
238
+ # config.client_wsdl_ssl_cert_key_file = 'caminho/client_key.pem'
239
+ # config.client_wsdl_ssl_cert_key_password = 'senha'
240
+ config.client_wsdl_ssl_verify_mode = :none
241
+ config.client_wsdl_ssl_cert_file = nil
242
+ config.client_wsdl_ssl_cert_key_file = nil
243
+ config.client_wsdl_ssl_cert_key_password = nil
244
+
245
+ # Se você quiser exibir em log a requisição SOAP, mude para true as opções a seguir
246
+ config.client_wsdl_log = false
247
+ config.client_wsdl_pretty_print_xml = false
248
+ end
249
+ ```
250
+
251
+
252
+ ## Objetivos futuros
253
+ * Emitir notas fiscais de produtos.
254
+ * Emitir notas fiscais de serviços para todas as cidades do Brasil.
255
+
256
+ ## Contribuições
257
+
258
+ Seja um contribuidor. Você pode contribuir de N formas. Seguem elas:
259
+
260
+ * Desenvolver emissão de NFS-e para outras cidades.
261
+ * Desenvolver emissão de NF-e (produtos).
262
+ * Refatorando código.
263
+ * Fornecendo Feedback construtivo (Sempre bem vindo!).
2
264
 
3
265
  ## Licença
4
266
 
data/br_nfe.gemspec CHANGED
@@ -1,15 +1,24 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.expand_path('../lib/br_nfe/version', __FILE__)
3
3
 
4
- Gem::Specification.new do |gem|
4
+ e = Gem::Specification.new do |gem|
5
5
  gem.authors = ["Bruno M. Mergen"]
6
6
  gem.email = ["brunomergen@gmail.com"]
7
7
  gem.description = %q{Emissão de Notas Fiscais Eletrônicas em Ruby}
8
- gem.summary = %q{Emissão de Notas Fiscais Eletrônicas em Ruby}
8
+ gem.summary = %q{BrNfe é uma gem para projetos Ruby on Rails que tem como objetifo facilitar e padronizar a emissão de Notas Fiscais eletrônicas}
9
9
  gem.homepage = "https://github.com/Brunomm/br_nfe"
10
10
  gem.license = "BSD"
11
11
 
12
- gem.files = `git ls-files`.split($\).reject { |f| ['.pdf','.xls'].include?(File.extname(f)) }
12
+ gem.files = `git ls-files`.split($\).reject do |file|
13
+ file =~ %r{^(?:
14
+ test/.*
15
+ |Gemfile
16
+ |Rakefile
17
+ |coverage/.*
18
+ |exemplos/.*
19
+ |\.travis.yml
20
+ )$}x
21
+ end
13
22
  gem.test_files = `git ls-files -- test/**/*`.split("\n")
14
23
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
24
  gem.name = "br_nfe"
@@ -18,11 +27,11 @@ Gem::Specification.new do |gem|
18
27
 
19
28
  gem.required_ruby_version = '>= 2.1'
20
29
 
21
- gem.add_dependency "rake", '>= 0.8.7'
30
+ gem.add_dependency "rake", '~> 10'
22
31
  gem.add_dependency "activesupport", '~> 4.2'
23
32
  gem.add_dependency "activemodel", '~> 4.2'
24
33
  gem.add_dependency "nokogiri", "~> 1.6"
25
34
  gem.add_dependency "savon", "~> 2.11"
26
- gem.add_dependency "signer"
35
+ gem.add_dependency "signer", "~> 1.4"
27
36
 
28
37
  end
data/lib/br_nfe/base.rb CHANGED
@@ -27,6 +27,11 @@ module BrNfe
27
27
  @env ||= :production
28
28
  end
29
29
 
30
+ def original_response
31
+ @original_response
32
+ end
33
+
34
+
30
35
  def response
31
36
  @response
32
37
  end
@@ -160,7 +165,7 @@ module BrNfe
160
165
 
161
166
  def validar_emitente
162
167
  if emitente.invalid?
163
- emitente.errors.full_messages.map{|msg| errors.add(:emitente, msg) }
168
+ emitente.errors.full_messages.map{|msg| errors.add(:base, "Emitente: #{msg}") }
164
169
  end
165
170
  end
166
171
 
@@ -18,11 +18,6 @@ module BrNfe
18
18
  sem_formatacao.size > 11 ? :cnpj : :cpf
19
19
  end
20
20
 
21
- def tipo_documento(tamanho = 2)
22
- return '0' if sem_formatacao.blank?
23
- sem_formatacao.size < 14 ? '1'.rjust(tamanho, '0') : '2'.rjust(tamanho, '0')
24
- end
25
-
26
21
  def sem_formatacao
27
22
  @cpf_cnpj.gsub(/[\.]|[\-]|[\/]/,'')
28
23
  end
@@ -1,11 +1,7 @@
1
1
  module BrNfe
2
2
  module Helper
3
3
  module HaveAddress
4
-
5
- def validar_endereco?
6
- true
7
- end
8
-
4
+
9
5
  def validar_endereco
10
6
  if endereco.invalid?
11
7
  endereco.errors.full_messages.each { |msg| errors.add(:base, "Endereço: #{msg}") }
@@ -21,6 +21,13 @@ module BrNfe
21
21
  rps.errors.full_messages.map{|msg| errors.add(:rps, msg) }
22
22
  end
23
23
  end
24
+
25
+ def valida_rps_recepcao
26
+ rps.validar_recepcao_rps = true
27
+ if rps.invalid?
28
+ rps.errors.full_messages.map{|msg| errors.add(:base, "RPS: #{msg}") }
29
+ end
30
+ end
24
31
 
25
32
  end
26
33
  end
@@ -8,17 +8,21 @@ module BrNfe
8
8
 
9
9
  private
10
10
 
11
- def tag_identificacao_rps(xml, rps)
12
- xml.IdentificacaoRps {
13
- dados_identificacao_rps(xml, rps)
14
- }
11
+ def xml_identificacao_rps(rps)
12
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
13
+ xml.IdentificacaoRps {
14
+ dados_identificacao_rps(xml, rps)
15
+ }
16
+ end
15
17
  end
16
18
 
17
- def tag_rps_substituido(xml, rps)
18
- return unless rps.contem_substituicao?
19
- xml.RpsSubstituido{
20
- dados_identificacao_rps(xml, rps, true)
21
- }
19
+ def xml_rps_substituido(rps)
20
+ return Nokogiri::XML::Builder.new unless rps.contem_substituicao?
21
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
22
+ xml.RpsSubstituido {
23
+ dados_identificacao_rps(xml, rps, true)
24
+ }
25
+ end
22
26
  end
23
27
 
24
28
  def dados_identificacao_rps(xml, rps, substituicao = false)
@@ -27,45 +31,52 @@ module BrNfe
27
31
  xml.Tipo "#{(substituicao ? rps.tipo_substituicao : rps.tipo)}".max_size(1)
28
32
  end
29
33
 
30
- def tag_dados_tomador(xml, destinatario)
31
- xml.Tomador{
32
- xml.IdentificacaoTomador {
33
- xml.CpfCnpj {
34
- tag_cpf_cnpj(xml, destinatario.cpf_cnpj)
34
+ def xml_dados_tomador(destinatario)
35
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
36
+ xml.Tomador{
37
+ xml.IdentificacaoTomador {
38
+ xml.CpfCnpj {
39
+ tag_cpf_cnpj(xml, destinatario.cpf_cnpj)
40
+ }
41
+ xml.InscricaoMunicipal "#{destinatario.inscricao_municipal}".max_size(15) if destinatario.inscricao_municipal.present?
42
+ xml.InscricaoEstadual "#{destinatario.inscricao_estadual}".max_size(15) if destinatario.inscricao_estadual.present? && version == :v1
35
43
  }
36
- xml.InscricaoMunicipal "#{destinatario.inscricao_municipal}".max_size(15) if destinatario.inscricao_municipal.present?
37
- xml.InscricaoEstadual "#{destinatario.inscricao_estadual}".max_size(15) if destinatario.inscricao_estadual.present? && version == :v1
38
- }
39
- xml.RazaoSocial "#{destinatario.razao_social}".max_size(115)
44
+ xml.RazaoSocial "#{destinatario.razao_social}".max_size(115)
40
45
 
41
- tag_endereco(xml, destinatario.endereco)
42
-
43
- xml.Contato {
44
- xml.Telefone BrNfe::Helper.only_number(destinatario.telefone).max_size(11) unless destinatario.telefone.blank?
45
- xml.Email "#{destinatario.email}".max_size(80) unless destinatario.email.blank?
46
+ # endereço
47
+ xml.__send__ :insert, Nokogiri::XML::DocumentFragment.parse( xml_endereco(destinatario.endereco).doc.root.to_s )
48
+
49
+ xml.Contato {
50
+ xml.Telefone BrNfe::Helper.only_number(destinatario.telefone).max_size(11) unless destinatario.telefone.blank?
51
+ xml.Email "#{destinatario.email}".max_size(80) unless destinatario.email.blank?
52
+ }
46
53
  }
47
- }
54
+ end
48
55
  end
49
56
 
50
- def tag_endereco(xml, endereco)
51
- xml.Endereco {
52
- xml.Endereco "#{endereco.logradouro}".max_size(125)
53
- xml.Numero "#{endereco.numero}".max_size(10)
54
- xml.Complemento "#{endereco.complemento}".max_size(60)
55
- xml.Bairro "#{endereco.bairro}".max_size(60)
56
- xml.CodigoMunicipio "#{endereco.codigo_municipio}".max_size(7)
57
- xml.Uf "#{endereco.uf}".max_size(2)
58
- xml.Cep BrNfe::Helper.only_number(endereco.cep).max_size(8)
59
- # xml.CodigoPais endereco.codigo_pais if version == :v2
60
- }
57
+ def xml_endereco(endereco, cod_pais=false)
58
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
59
+ xml.Endereco {
60
+ xml.Endereco "#{endereco.logradouro}".max_size(125)
61
+ xml.Numero "#{endereco.numero}".max_size(10)
62
+ xml.Complemento "#{endereco.complemento}".max_size(60)
63
+ xml.Bairro "#{endereco.bairro}".max_size(60)
64
+ xml.CodigoMunicipio BrNfe::Helper.only_number(endereco.codigo_municipio).max_size(7)
65
+ xml.Uf "#{endereco.uf}".max_size(2)
66
+ xml.Cep BrNfe::Helper.only_number(endereco.cep).max_size(8)
67
+ xml.CodigoPais BrNfe::Helper.only_number(endereco.codigo_pais).max_size(4) if version == :v2 && cod_pais
68
+ }
69
+ end
61
70
  end
62
71
 
63
- def tag_dados_construcao_civil(xml, rps)
64
- return if rps.codigo_obra.blank? || rps.codigo_art.blank?
65
- xml.ConstrucaoCivil{
66
- xml.CodigoObra "#{rps.codigo_obra}".max_size(15)
67
- xml.Art "#{rps.codigo_art}".max_size(15)
68
- }
72
+ def xml_dados_construcao_civil(rps)
73
+ return Nokogiri::XML::Builder.new if rps.codigo_obra.blank? || rps.codigo_art.blank?
74
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
75
+ xml.ConstrucaoCivil{
76
+ xml.CodigoObra "#{rps.codigo_obra}".max_size(15)
77
+ xml.Art "#{rps.codigo_art}".max_size(15)
78
+ }
79
+ end
69
80
  end
70
81
 
71
82
  end
@@ -0,0 +1,141 @@
1
+ module BrNfe
2
+ module Servico
3
+ module Betha
4
+ class BuildResponse < BrNfe::ActiveModelBase
5
+ attr_accessor :nfe_method
6
+
7
+ def initialize(attributes = {})
8
+ @error_messages = []
9
+ super(attributes)
10
+ end
11
+
12
+ def success?
13
+ error_messages.blank?
14
+ end
15
+
16
+ def response
17
+ @response ||= BrNfe::Servico::Response::Default.new do |resp|
18
+ resp.success = success?
19
+ resp.error_messages = error_messages
20
+ resp.notas_fiscais = get_notas_fiscais
21
+ resp.protocolo = messages[:protocolo]
22
+ resp.data_recebimento = messages[:data_recebimento]
23
+ resp.numero_lote = messages[:numero_lote]
24
+ end
25
+ end
26
+
27
+ def error_messages
28
+ return @error_messages unless @error_messages.blank?
29
+
30
+ get_messages!(messages[:lista_nfse][:listamensagem_alerta_retorno]) if messages[:lista_nfse]
31
+ get_messages!(messages[:lista_mensagem_retorno])
32
+ get_messages!(messages[:lista_mensagem_retorno_lote])
33
+
34
+ @error_messages
35
+ end
36
+
37
+ private
38
+
39
+ def get_notas_fiscais
40
+ @notas_fiscais = []
41
+ return @notas_fiscais if messages[:lista_nfse].blank? || messages[:lista_nfse][key_complemento_nfse].blank?
42
+ comp_nfse = messages[:lista_nfse][key_complemento_nfse]
43
+
44
+ if comp_nfse.is_a?(Hash)
45
+ @notas_fiscais << new_nota_fiscal(comp_nfse)
46
+ elsif comp_nfse.is_a?(Array)
47
+ comp_nfse.map{|p| @notas_fiscais << new_nota_fiscal(p) }
48
+ end
49
+ @notas_fiscais
50
+ end
51
+
52
+ def get_messages!(msgs)
53
+ return unless msgs
54
+ msgs = msgs[:mensagem_retorno]
55
+ if msgs.is_a?(Hash)
56
+ @error_messages << get_message(msgs)
57
+ elsif msgs.is_a?(Array)
58
+ msgs.each do |msg|
59
+ @error_messages << get_message(msg)
60
+ end
61
+ end
62
+ end
63
+
64
+ def get_message(hash)
65
+ if hash[:identificacao_rps]
66
+ {
67
+ codigo: hash[:codigo],
68
+ mensagem: hash[:mensagem],
69
+ rps: {
70
+ numero: hash[:identificacao_rps][:numero],
71
+ serie: hash[:identificacao_rps][:serie],
72
+ tipo: hash[:identificacao_rps][:tipo],
73
+ }
74
+ }
75
+ else
76
+ {
77
+ codigo: hash[:codigo],
78
+ mensagem: hash[:mensagem],
79
+ correcao: hash[:correcao]
80
+ }
81
+ end
82
+ end
83
+
84
+ def get_construcao_civil(nfse, params)
85
+ params ||= {}
86
+ nfse.codigo_obra = params[:codigo_obra]
87
+ nfse.codigo_art = params[:art]
88
+ end
89
+
90
+ def get_info_substituicao(nfse, params)
91
+ params ||= {}
92
+ params = params[:substituicao_nfse] || {}
93
+
94
+ nfse.nfe_substituidora = params[:nfse_substituidora]
95
+ end
96
+
97
+
98
+ def get_orgao_gerador(nfse, params)
99
+ params ||= {}
100
+ nfse.orgao_gerador_municipio = params[:codigo_municipio]
101
+ nfse.orgao_gerador_uf = params[:uf]
102
+ end
103
+
104
+ def get_destinatario_servico(nfse, params)
105
+ params ||= {}
106
+ nfse.destinatario do |dest|
107
+ if identificacao = params[:identificacao_tomador]
108
+ dest.cpf_cnpj = identificacao[:cpf_cnpj][:cnpj] || identificacao[:cpf_cnpj][:cpf] if identificacao[:cpf_cnpj]
109
+ dest.inscricao_municipal = identificacao[:inscricao_municipal]
110
+ dest.inscricao_estadual = identificacao[:inscricao_estadual]
111
+ end
112
+ dest.razao_social = params[:razao_social]
113
+ dest.nome_fantasia = params[:nome_fantasia]
114
+ if params[:contato]
115
+ dest.telefone = params[:contato][:telefone]
116
+ dest.email = params[:contato][:email]
117
+ end
118
+ dest.endereco = get_endereco(params[:endereco])
119
+ end
120
+ end
121
+
122
+
123
+ def get_endereco(params)
124
+ params ||= {}
125
+ BrNfe::Endereco.new do |e|
126
+ e.logradouro = params[:endereco]
127
+ e.numero = params[:numero]
128
+ e.complemento = params[:complemento]
129
+ e.bairro = params[:bairro]
130
+ e.nome_municipio = params[:nome_municipio]
131
+ e.codigo_municipio = params[:codigo_municipio]
132
+ e.uf = params[:uf]
133
+ e.cep = params[:cep]
134
+ e.codigo_pais = params[:codigo_pais] if params[:codigo_pais]
135
+ e.nome_pais = params[:nome_pais] if params[:nome_pais]
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end