rnfse 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +7 -6
  4. data/lib/provedores.yml +8 -0
  5. data/lib/rnfse.rb +5 -1
  6. data/lib/rnfse/api.rb +44 -22
  7. data/lib/rnfse/api/abrasf_1_0.rb +100 -17
  8. data/lib/rnfse/api/abrasf_1_0/#definitions.json# +413 -0
  9. data/lib/rnfse/api/abrasf_1_0/cancelar_nfse.json +13 -0
  10. data/lib/rnfse/api/abrasf_1_0/consultar_nfse.json +17 -0
  11. data/lib/rnfse/api/abrasf_1_0/consultar_nfse_por_rps.json +13 -0
  12. data/lib/rnfse/api/abrasf_1_0/definitions.json +27 -3
  13. data/lib/rnfse/api/abrasf_1_0/recepcionar_lote_rps.json +1 -1
  14. data/lib/rnfse/api/iss_net_1_0.rb +46 -2
  15. data/lib/rnfse/api/speed_gov_1_0.rb +115 -0
  16. data/lib/rnfse/call_chain.rb +4 -4
  17. data/lib/rnfse/error.rb +15 -0
  18. data/lib/rnfse/hash.rb +24 -11
  19. data/lib/rnfse/string.rb +16 -2
  20. data/lib/rnfse/version.rb +1 -1
  21. data/lib/rnfse/xml_builder/abrasf_1_0.rb +103 -13
  22. data/lib/rnfse/xml_builder/iss_net_1_0.rb +34 -4
  23. data/lib/rnfse/xml_builder/speed_gov_1_0.rb +158 -0
  24. data/spec/api/abrasf_1_0/cancelar_nfse_json_spec.rb +25 -0
  25. data/spec/api/abrasf_1_0/consultar_lote_rps_json_spec.rb +23 -0
  26. data/spec/api/abrasf_1_0/consultar_nfse_json_spec.rb +45 -0
  27. data/spec/api/abrasf_1_0/consultar_nfse_por_rps_json_spec.rb +23 -0
  28. data/spec/api/abrasf_1_0/consultar_situacao_lote_rps_json_spec.rb +23 -0
  29. data/spec/api/abrasf_1_0_spec.rb +185 -6
  30. data/spec/api/iss_net_1_0_spec.rb +89 -9
  31. data/spec/api/speed_gov_1_0_spec.rb +243 -0
  32. data/spec/api_spec.rb +43 -28
  33. data/spec/error_spec.rb +10 -0
  34. data/spec/fixtures/abrasf_1_0/cancelar_nfse_envio.xml +16 -0
  35. data/spec/fixtures/abrasf_1_0/consultar_nfse.xml +23 -0
  36. data/spec/fixtures/abrasf_1_0/consultar_nfse_por_rps.xml +14 -0
  37. data/spec/fixtures/iss_net_1_0/cancelar_nfse_envio.xml +17 -0
  38. data/spec/fixtures/iss_net_1_0/consultar_nfse.xml +29 -0
  39. data/spec/fixtures/iss_net_1_0/consultar_nfse_por_rps.xml +17 -0
  40. data/spec/fixtures/speed_gov_1_0/consultar_nfse_envio.xml +29 -0
  41. data/spec/fixtures/speed_gov_1_0/consultar_nfse_rps_envio.xml +16 -0
  42. data/spec/fixtures/speed_gov_1_0/consultar_situacao_lote_rps_envio.xml +12 -0
  43. data/spec/fixtures/speed_gov_1_0/enviar_lote_rps_envio.xml +82 -0
  44. data/spec/fixtures/speed_gov_1_0/header.xml +9 -0
  45. data/spec/fixtures/vcr_cassettes/iss_net_1_0_cancelar_nfse.yml +107 -0
  46. data/spec/fixtures/vcr_cassettes/iss_net_1_0_consultar_nfse.yml +7937 -0
  47. data/spec/fixtures/vcr_cassettes/iss_net_1_0_consultar_nfse_por_rps.yml +242 -0
  48. data/spec/fixtures/vcr_cassettes/speed_gov_1_0_consultar_nfse.yml +60 -0
  49. data/spec/fixtures/vcr_cassettes/speed_gov_1_0_consultar_nfse_por_rps.yml +80 -0
  50. data/spec/fixtures/vcr_cassettes/speed_gov_1_0_consultar_situacao_lote_rps.yml +77 -0
  51. data/spec/fixtures/vcr_cassettes/speed_gov_1_0_recepcionar_lote_rps.yml +171 -0
  52. data/spec/fixtures/vcr_cassettes/speed_gov_1_0_recepcionar_lote_rps_ascii.yml +171 -0
  53. data/spec/hash_spec.rb +21 -0
  54. data/spec/spec_helper.rb +2 -0
  55. data/spec/string_spec.rb +31 -5
  56. data/spec/xml_builder/abrasf_1_0_spec.rb +110 -43
  57. data/spec/xml_builder/iss_net_1_0_spec.rb +111 -44
  58. data/spec/xml_builder/speed_gov_1_0_spec.rb +173 -0
  59. metadata +86 -37
  60. data/.gitignore +0 -25
  61. data/.rspec +0 -1
  62. data/.travis.yml +0 -14
  63. data/Gemfile +0 -3
  64. data/Guardfile +0 -15
  65. data/Procfile +0 -1
  66. data/Rakefile +0 -12
  67. data/rnfse.gemspec +0 -61
  68. data/spec/fixtures/abrasf_1_0/teste.xml +0 -8
  69. data/spec/support/.keep +0 -0
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Cancelamento de NFS-e",
4
+ "description": "Esse serviço permite o cancelamento direto de uma NFS-e sem substituição da mesma por outra.",
5
+
6
+ "type": "object",
7
+ "properties": {
8
+ "identificacaoNfse": { "$ref": "definitions.json#/identificacaoNfse"},
9
+ "codigoCancelamento": { "$ref": "definitions.json#/codigoCancelamentoNfse"}
10
+ },
11
+ "required": ["identificacaoNfse", "codigoCancelamento"],
12
+ "additionalProperties": false
13
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Consulta de NFS-e",
4
+ "description": "Esse serviço permite a obtenção de determinada NFS-e já gerada.",
5
+
6
+ "type": "object",
7
+ "properties": {
8
+ "prestador": { "$ref": "definitions.json#/identificacaoPrestador" },
9
+ "numeroNfse": { "$ref": "definitions.json#/numeroNfse" },
10
+ "dataInicial": { "$ref": "definitions.json#/data" },
11
+ "dataFinal": { "$ref": "definitions.json#/data" },
12
+ "tomador": { "$ref": "definitions.json#/identificacaoTomador" },
13
+ "intermediarioServico": { "$ref": "definitions.json#/identificacaoIntermediarioServico" }
14
+ },
15
+ "required": ["prestador"],
16
+ "additionalProperties": false
17
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Consulta de NFS-e por RPS",
4
+ "description": "Esse serviço efetua a consulta de uma NFS-e a partir do número de RPS que a gerou.",
5
+
6
+ "type": "object",
7
+ "properties": {
8
+ "identificacaoRps": { "$ref": "definitions.json#/identificacaoRps" },
9
+ "prestador": { "$ref": "definitions.json#/identificacaoPrestador" }
10
+ },
11
+ "required": ["identificacaoRps", "prestador"],
12
+ "additionalProperties": false
13
+ }
@@ -2,7 +2,7 @@
2
2
  "numeroNfse": {
3
3
  "description": "Número da Nota Fiscal de Serviço Eletrônica, formado pelo ano com 04 (quatro) dígitos e um número seqüencial com 11 posições – Formato AAAANNNNNNNNNNN.",
4
4
  "type": "integer",
5
- "minimum": 199000000000000,
5
+ "minimum": 190000000000000,
6
6
  "maximum": 220099999999999
7
7
  },
8
8
  "codigoVerificacao": {
@@ -46,7 +46,7 @@
46
46
  "numeroRps": {
47
47
  "description": "Número do RPS",
48
48
  "type": "integer",
49
- "minimum": 1,
49
+ "minimum": 0,
50
50
  "maximum": 999999999999999
51
51
  },
52
52
  "serieRps": {
@@ -369,7 +369,9 @@
369
369
  {
370
370
  "type": "object",
371
371
  "properties": {
372
- "cpf": { "$ref": "#/cpf" }
372
+ "razaoSocial": { "$ref": "#/razaoSocial" },
373
+ "cpf": { "$ref": "#/cpf" },
374
+ "inscricaoMunicipal": { "$ref": "#/inscricaoMunicipal" }
373
375
  },
374
376
  "required": ["cpf"],
375
377
  "additionalProperties": false
@@ -385,5 +387,27 @@
385
387
  },
386
388
  "required": [],
387
389
  "additionalProperties": false
390
+ },
391
+ "data": {
392
+ "description": "Data como representada no padrão RFC 3339 section 5.6",
393
+ "type": "string",
394
+ "format": "date-time"
395
+ },
396
+ "codigoCancelamentoNfse": {
397
+ "description": "Código de cancelamento com base na tabela de erros e alertas",
398
+ "type": "string",
399
+ "maxLength": 4
400
+ },
401
+ "identificacaoNfse": {
402
+ "description": "Representa dados que identificam uma Nota Fiscal de Serviços Eletrônica",
403
+ "type": "object",
404
+ "properties": {
405
+ "numero": { "$ref": "#/numeroNfse" },
406
+ "cnpj": { "$ref": "#/cnpj" },
407
+ "inscricaoMunicipal": { "$ref": "#/inscricaoMunicipal" },
408
+ "codigoMunicipio": { "$ref": "#/codigoMunicipioIbge" }
409
+ },
410
+ "required": ["numero", "cnpj"],
411
+ "additionalProperties": false
388
412
  }
389
413
  }
@@ -18,7 +18,7 @@
18
18
  "type": "object",
19
19
  "properties": {
20
20
  "identificacaoRps": { "$ref": "definitions.json#/identificacaoRps" },
21
- "dataEmissao": { "type": "string", "format": "date-time" },
21
+ "dataEmissao": { "$ref": "definitions.json#/data" },
22
22
  "naturezaOperacao": { "$ref": "definitions.json#/naturezaOperacao" },
23
23
  "regimeEspecialTributacao": { "$ref": "definitions.json#/regimeEspecialTributacao" },
24
24
  "optanteSimplesNacional": { "type": "boolean" },
@@ -1,11 +1,32 @@
1
1
  # -*- coding: utf-8 -*-
2
- require 'json-schema'
3
2
 
4
3
  module Rnfse::API::IssNet10
5
4
  include Rnfse::API::Abrasf10
6
5
 
6
+ def operations()
7
+ [
8
+ :recepcionar_lote_rps, :consultar_situacao_lote_rps,
9
+ :consultar_nfse_por_rps, :consultar_nfse, :consultar_lote_rps,
10
+ :cancelar_nfse, :consultar_url_visualizacao_nfse,
11
+ :consultar_url_visualizacao_nfse_serie
12
+ ]
13
+ end
14
+
15
+ # def recepcionar_lote_rps(hash = {})
16
+ # validate_sign_options
17
+ # validate_options(hash)
18
+ # xml = xml_builder.build_recepcionar_lote_rps_xml(hash)
19
+ # xml.sign!(certificate: File.read(self.certificate), key: File.read(self.key))
20
+ # response = self.soap_client.call(
21
+ # :recepcionar_lote_rps,
22
+ # soap_action: 'RecepcionarLoteRps',
23
+ # message_tag: 'RecepcionarLoteRps',
24
+ # message: { :'xml!' => "<![CDATA[#{xml}]]>" })
25
+ # parse_response(response)
26
+ # end
27
+
7
28
  def consultar_situacao_lote_rps(hash = {})
8
- validate(hash)
29
+ validate_options(hash)
9
30
  xml = xml_builder.build_consultar_situacao_lote_rps_xml(hash)
10
31
  response = self.soap_client.call(
11
32
  :consultar_situacao_lote_rps,
@@ -15,4 +36,27 @@ module Rnfse::API::IssNet10
15
36
  parse_response(response)
16
37
  end
17
38
 
39
+ def consultar_nfse_por_rps(hash = {})
40
+ validate_options(hash)
41
+ xml = xml_builder.build_consultar_nfse_por_rps_xml(hash)
42
+ response = self.soap_client.call(
43
+ :consultar_nfse_por_rps,
44
+ soap_action: 'ConsultarNFSePorRPS',
45
+ message_tag: 'ConsultarNFSePorRPS',
46
+ message: { :'xml!' => "<![CDATA[#{xml}]]>" })
47
+ parse_response(response)
48
+ end
49
+
50
+ def consultar_url_visualizacao_nfse(hash = {})
51
+ raise Rnfse::Error::NotImplemented
52
+ end
53
+
54
+ def consultar_url_visualizacao_nfse_serie(hash = {})
55
+ raise Rnfse::Error::NotImplemented
56
+ end
57
+
58
+ def json_folder
59
+ 'iss_net_1_0'
60
+ end
61
+
18
62
  end
@@ -0,0 +1,115 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Rnfse::API::SpeedGov10
4
+ include Rnfse::API::Abrasf10
5
+
6
+ def recepcionar_lote_rps(hash = {})
7
+ validate_sign_options
8
+ validate_options(hash)
9
+ validate_ascii(hash)
10
+ header = xml_builder.build_header_xml()
11
+ parameters = xml_builder.build_recepcionar_lote_rps_xml(hash)
12
+ parameters.sign!(certificate: File.read(self.certificate), key: File.read(self.key))
13
+ response = self.soap_client.call(
14
+ :recepcionar_lote_rps,
15
+ soap_action: 'RecepcionarLoteRps',
16
+ message_tag: 'nfse:RecepcionarLoteRps',
17
+ message: { :'header!' => "<![CDATA[#{header}]]>",
18
+ :'parameters!' => "<![CDATA[#{parameters}]]>" })
19
+ parse_response(response)
20
+ end
21
+
22
+ def consultar_situacao_lote_rps(hash = {})
23
+ validate_options(hash)
24
+ header = xml_builder.build_header_xml()
25
+ parameters = xml_builder.build_consultar_situacao_lote_rps_envio_xml(hash)
26
+ response = self.soap_client.call(
27
+ :consultar_situacao_lote_rps,
28
+ soap_action: 'ConsultarSituacaoLoteRps',
29
+ message_tag: 'nfse:ConsultarSituacaoLoteRps',
30
+ message: { :'header!' => "<![CDATA[#{header}]]>",
31
+ :'parameters!' => "<![CDATA[#{parameters}]]>" })
32
+ parse_response(response)
33
+ end
34
+
35
+ def consultar_lote_rps(hash = {})
36
+ raise Rnfse::Error::NotImplemented
37
+ end
38
+
39
+ def consultar_nfse_por_rps(hash = {})
40
+ validate_options(hash)
41
+ validate_ascii(hash)
42
+ header = xml_builder.build_header_xml()
43
+ parameters = xml_builder.build_consultar_nfse_rps_envio_xml(hash)
44
+ response = self.soap_client.call(
45
+ :consultar_nfse_por_rps,
46
+ soap_action: 'ConsultarNfsePorRps',
47
+ message_tag: 'nfse:ConsultarNfsePorRps',
48
+ message: { :'header!' => "<![CDATA[#{header}]]>",
49
+ :'parameters!' => "<![CDATA[#{parameters}]]>" })
50
+ parse_response(response)
51
+ end
52
+
53
+ def consultar_nfse(hash = {})
54
+ validate_options(hash)
55
+ header = xml_builder.build_header_xml()
56
+ parameters = xml_builder.build_consultar_nfse_envio_xml(hash)
57
+ response = self.soap_client.call(
58
+ :consultar_situacao_lote_rps,
59
+ soap_action: 'ConsultarNfse',
60
+ message_tag: 'nfse:ConsultarNfse',
61
+ message: { :'header!' => "<![CDATA[#{header}]]>",
62
+ :'parameters!' => "<![CDATA[#{parameters}]]>" })
63
+ parse_response(response)
64
+ end
65
+
66
+ def cancelar_nfse(hash = {})
67
+ raise Rnfse::Error::NotImplemented
68
+ end
69
+
70
+ private
71
+
72
+ def validate_ascii(hash)
73
+ raise Rnfse::Error::NonASCIIEncoding unless hash.to_s.ascii_only?
74
+ end
75
+
76
+ def load_options_for_production(options)
77
+ provedor = provedores['producao'][options['provedor'].to_s]
78
+ self.namespace = provedor['namespace']
79
+ municipio = case options['municipio'].to_s
80
+ when 'petrolina' then 'pet'
81
+ when 'aquiraz' then 'aqz'
82
+ else options['municipio'].to_s
83
+ end
84
+ self.endpoint = provedor['endpoint'] % { municipio: municipio }
85
+ load_default_options(options)
86
+ end
87
+
88
+ def parse_response(response)
89
+ hash = Rnfse::Hash.new(response.body)
90
+ response_key = hash.keys.select { |k| k =~ /response$/ }.first
91
+ return_key = hash[response_key].keys.select { |k| k =~ /return$/ }.first
92
+ if !hash[response_key].nil? and hash[response_key]
93
+ xml = hash[response_key][return_key]
94
+ hash[response_key][return_key] = Nori.new.parse(xml)
95
+ end
96
+ hash.underscore_and_symbolize_keys
97
+ end
98
+
99
+ def savon_client_options
100
+ {
101
+ soap_version: 1,
102
+ env_namespace: :soapenv,
103
+ namespaces: { 'xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
104
+ 'xmlns:nfse' => 'http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd',
105
+ 'xmlns' => '' },
106
+ namespace_identifier: nil,
107
+ ssl_verify_mode: :peer,
108
+ ssl_cert_file: self.certificate,
109
+ ssl_cert_key_file: self.key,
110
+ endpoint: self.endpoint,
111
+ namespace: self.namespace
112
+ }
113
+ end
114
+
115
+ end
@@ -7,13 +7,13 @@ module Rnfse
7
7
 
8
8
  private
9
9
 
10
- # Stolen from ActionMailer, where this was used but was not made
11
- # reusable
10
+ # Stolen from ActionMailer with a tweek,
11
+ # where this was used but was not made reusable
12
12
  def self.parse_caller(at)
13
- if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
13
+ if /^(.+?):(\d+)(?::in `((block in )?(.*))')?/ =~ at
14
14
  file = Regexp.last_match[1]
15
15
  line = Regexp.last_match[2].to_i
16
- method = Regexp.last_match[3]
16
+ method = Regexp.last_match[5]
17
17
  [file, line, method]
18
18
  end
19
19
  end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Rnfse
3
+ class Error
4
+ # Metodos não implementados
5
+ class NotImplemented < ::NotImplementedError; end
6
+
7
+ # Ações de API que tem comportamento anômalo.
8
+ # Em alguns provedores algumas ações, embora implemenadas não
9
+ # funcionam ou tem comportamento anômalo.
10
+ class BetterNotBeUsed < ::StandardError; end
11
+
12
+ # Caracteres fora do padrão ASCII foram utilizados.
13
+ class NonASCIIEncoding < ::StandardError; end
14
+ end
15
+ end
@@ -58,18 +58,24 @@ module Rnfse
58
58
  self.class.underscore_and_symbolize_keys(self)
59
59
  end
60
60
 
61
- def self.transform_keys(obj, &block)
61
+ def self.transform_keys(obj, regex = nil, &block)
62
+ regex = /.*/ if regex.nil?
63
+
62
64
  case
63
65
  when obj.kind_of?(::Hash)
64
66
  result = {}
65
67
  obj.each_key do |key|
66
- result[yield(key)] = self.transform_keys(obj[key], &block)
68
+ if regex.match(key)
69
+ result[yield(key)] = self.transform_keys(obj[key], regex, &block)
70
+ else
71
+ result[key] = self.transform_keys(obj[key], regex, &block)
72
+ end
67
73
  end
68
74
  result
69
75
  when obj.kind_of?(::Array)
70
76
  result = []
71
77
  obj.each do |elem|
72
- result << self.transform_keys(elem, &block)
78
+ result << self.transform_keys(elem, regex, &block)
73
79
  end
74
80
  result
75
81
  else
@@ -77,8 +83,8 @@ module Rnfse
77
83
  end
78
84
  end
79
85
 
80
- def transform_keys(&block)
81
- self.class.transform_keys(self, &block)
86
+ def transform_keys(regex = nil, &block)
87
+ self.class.transform_keys(self, regex, &block)
82
88
  end
83
89
 
84
90
  def self.transform_values(obj, key, &block)
@@ -111,19 +117,26 @@ module Rnfse
111
117
  end
112
118
 
113
119
  def self.replace_key_values(obj, key, &block)
114
- parent = key.to_s.split('/').first
115
- childs = key.to_s.split('/')[1..-1]
116
- regex = key.kind_of?(::Regexp) ? key : /\A#{parent}\Z/
120
+ parent, children = case
121
+ when key.kind_of?(::Regexp)
122
+ [ key, [] ]
123
+ when key.kind_of?(::Array)
124
+ [ key.first, key[1..-1] ]
125
+ else
126
+ parts = key.to_s.split('/')
127
+ [ parts.first, parts[1..-1] ]
128
+ end
129
+ regex = parent.kind_of?(::Regexp) ? parent : /\A#{parent}\Z/
117
130
 
118
131
  case
119
132
  when obj.kind_of?(::Hash)
120
133
  result = {}
121
134
  obj.each_key do |k|
122
135
  case
123
- when (regex.match(k) and childs.empty?)
136
+ when (regex.match(k) and children.empty?)
124
137
  result.merge!(yield(k, obj[k]))
125
- when (regex.match(k) and !childs.empty?)
126
- result[k] = self.replace_key_values(obj[k], childs.join('/'), &block)
138
+ when (regex.match(k) and !children.empty?)
139
+ result[k] = self.replace_key_values(obj[k], children, &block)
127
140
  else
128
141
  result[k] = self.replace_key_values(obj[k], key, &block)
129
142
  end
@@ -11,7 +11,7 @@ module Rnfse
11
11
  end
12
12
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { $2.capitalize }
13
13
  string.gsub!('/', '::')
14
- string
14
+ self.new(string)
15
15
  end
16
16
 
17
17
  def camelize
@@ -26,11 +26,25 @@ module Rnfse
26
26
  word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
27
27
  word.tr!("-", "_")
28
28
  word.downcase!
29
- word
29
+ self.new(word)
30
30
  end
31
31
 
32
32
  def underscore
33
33
  self.class.underscore(self)
34
34
  end
35
+
36
+ def self.demodulize(path)
37
+ path = path.to_s
38
+ self.new( if i = path.rindex('::')
39
+ path[(i+2)..-1]
40
+ else
41
+ path
42
+ end )
43
+ end
44
+
45
+ def demodulize
46
+ self.class.demodulize(self)
47
+ end
48
+
35
49
  end
36
50
  end
@@ -1,3 +1,3 @@
1
1
  module Rnfse
2
- VERSION = '0.3.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -5,15 +5,51 @@ module Rnfse::XMLBuilder::Abrasf10
5
5
  module ClassMethods
6
6
 
7
7
  def build_recepcionar_lote_rps_xml(hash = {})
8
- build_xml('EnviarLoteRpsEnvio', hash)
8
+ if block_given?
9
+ build_xml('EnviarLoteRpsEnvio', hash, &Proc.new)
10
+ else
11
+ build_xml('EnviarLoteRpsEnvio', hash)
12
+ end
13
+ end
14
+
15
+ def build_consultar_situacao_lote_rps_xml(hash = {})
16
+ if block_given?
17
+ build_xml('ConsultarSituacaoLoteRpsEnvio', hash, &Proc.new)
18
+ else
19
+ build_xml('ConsultarSituacaoLoteRpsEnvio', hash)
20
+ end
21
+ end
22
+
23
+ def build_consultar_nfse_por_rps_xml(hash = {})
24
+ if block_given?
25
+ build_xml('ConsultarNfseRpsEnvio', hash, &Proc.new)
26
+ else
27
+ build_xml('ConsultarNfseRpsEnvio', hash)
28
+ end
29
+ end
30
+
31
+ def build_consultar_nfse_xml(hash = {})
32
+ if block_given?
33
+ build_xml('ConsultarNfseEnvio', hash, &Proc.new)
34
+ else
35
+ build_xml('ConsultarNfseEnvio', hash)
36
+ end
9
37
  end
10
38
 
11
39
  def build_consultar_lote_rps_xml(hash = {})
12
- build_xml('ConsultarLoteRpsEnvio', hash)
40
+ if block_given?
41
+ build_xml('ConsultarLoteRpsEnvio', hash, &Proc.new)
42
+ else
43
+ build_xml('ConsultarLoteRpsEnvio', hash)
44
+ end
13
45
  end
14
46
 
15
- def build_consultar_situacao_lote_rps_xml(hash = {})
16
- build_xml('ConsultarSituacaoLoteRpsEnvio', hash)
47
+ def build_cancelar_nfse_xml(hash = {})
48
+ if block_given?
49
+ build_xml('CancelarNfseEnvio', hash, &Proc.new)
50
+ else
51
+ build_xml('CancelarNfseEnvio', hash)
52
+ end
17
53
  end
18
54
 
19
55
  private
@@ -21,6 +57,7 @@ module Rnfse::XMLBuilder::Abrasf10
21
57
  def build_xml(wrapper, hash = {})
22
58
  hash = prepare_hash(hash)
23
59
  inner_xml = ::Gyoku.xml(hash, key_converter: :none)
60
+ inner_xml = yield(Nokogiri::XML(inner_xml)) if block_given?
24
61
  xml_builder(wrapper, inner_xml).doc
25
62
  end
26
63
 
@@ -28,6 +65,8 @@ module Rnfse::XMLBuilder::Abrasf10
28
65
  def prepare_hash(hash)
29
66
  hash = camelize_hash(hash)
30
67
  hash = wrap_rps(hash)
68
+ hash = wrap_periodo_emissao(hash)
69
+ hash = wrap_identificacao_nfse(hash)
31
70
  hash = add_tc_namespace(hash)
32
71
  hash = clean_numerics(hash)
33
72
  hash = date_to_utc(hash)
@@ -37,7 +76,7 @@ module Rnfse::XMLBuilder::Abrasf10
37
76
 
38
77
  # converte booleanos para 1 ou 2
39
78
  def fix_booleans(hash)
40
- regex = /(IssRetido|OptanteSimplesNacional|IncentivadorCultural)\Z/
79
+ regex = /((?<!Valor)IssRetido|OptanteSimplesNacional|IncentivadorCultural)\Z/
41
80
  Rnfse::Hash.transform_values(hash, regex) do |val|
42
81
  val ? 1 : 2
43
82
  end
@@ -46,7 +85,7 @@ module Rnfse::XMLBuilder::Abrasf10
46
85
  # converte datas para GMT-0
47
86
  def date_to_utc(hash)
48
87
  Rnfse::Hash.transform_values(hash, /DataEmissao\Z/) do |val|
49
- DateTime.parse(val).new_offset(0).strftime('%FT%T')
88
+ DateTime.parse(val.to_s).new_offset(0).strftime('%FT%T')
50
89
  end
51
90
  end
52
91
 
@@ -69,16 +108,43 @@ module Rnfse::XMLBuilder::Abrasf10
69
108
  hash
70
109
  end
71
110
 
111
+ # encapsula as tags data_inicial e data_final em periodo_emissao
112
+ def wrap_periodo_emissao(hash)
113
+ if hash[:DataInicial] or hash[:DataFinal]
114
+ hash[:PeriodoEmissao] = {
115
+ :DataInicial => hash.delete(:DataInicial),
116
+ :DataFinal => hash.delete(:DataFinal)
117
+ }
118
+ end
119
+ hash
120
+ end
121
+
122
+ # encapsula a tag identificacao_nfse
123
+ def wrap_identificacao_nfse(hash)
124
+ if hash[:IdentificacaoNfse]
125
+ hash[:Pedido] = {
126
+ :InfPedidoCancelamento => {
127
+ :IdentificacaoNfse => hash.delete(:IdentificacaoNfse),
128
+ :CodigoCancelamento => hash.delete(:CodigoCancelamento)
129
+ }
130
+ }
131
+ end
132
+ hash
133
+ end
134
+
72
135
  # adiciona o namespace tc nas tags dentro de loteRps ou prestador
73
136
  def add_tc_namespace(hash)
74
- tag = case
75
- when !hash[:LoteRps].nil? then :LoteRps
76
- when !hash[:Prestador].nil? then :Prestador
77
- end
78
- if hash[tag]
79
- hash[tag] = Rnfse::Hash.transform_keys(hash[tag]) { |key| "tc:#{key}".to_sym }
137
+ regex = %r{ \A(
138
+ LoteRps|
139
+ Prestador|
140
+ IdentificacaoRps|
141
+ Tomador|
142
+ IntermediarioServico|
143
+ Pedido
144
+ )\Z }x
145
+ Rnfse::Hash.replace_key_values(hash, regex) do |key, value|
146
+ { key => Rnfse::Hash.transform_keys(value) { |k| "tc:#{k}".to_sym } }
80
147
  end
81
- hash
82
148
  end
83
149
 
84
150
  # namespace dos tipos complexos
@@ -110,6 +176,30 @@ module Rnfse::XMLBuilder::Abrasf10
110
176
  }
111
177
  end
112
178
 
179
+ # namespaces do xml consultar_nfse_por_rps
180
+ def build_consultar_nfse_por_rps_xmlns
181
+ {
182
+ 'xmlns' => 'http://www.abrasf.org.br/servico_consultar_situacao_lote_rps_envio.xsd',
183
+ 'xmlns:tc' => xmlns_tc
184
+ }
185
+ end
186
+
187
+ # namespaces do xml consultar_nfse
188
+ def build_consultar_nfse_xmlns
189
+ {
190
+ 'xmlns' => 'http://www.abrasf.org.br/servico_consultar_nfse_envio.xsd',
191
+ 'xmlns:tc' => xmlns_tc
192
+ }
193
+ end
194
+
195
+ # namespaces do xml cancelar_nfse
196
+ def build_cancelar_nfse_xmlns
197
+ {
198
+ 'xmlns' => 'http://www.abrasf.org.br/servico_cancelar_nfse_envio.xsd',
199
+ 'xmlns:tc' => xmlns_tc
200
+ }
201
+ end
202
+
113
203
  # instancia o builder a ser utilizado na geracao do xml
114
204
  def xml_builder(root, inner_xml, xmlns = {})
115
205
  xmlns = self.send("#{Rnfse::CallChain.caller_method(2)}ns") if xmlns.empty?