br_nfe 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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