rnfse 0.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.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +1 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +3 -0
- data/Guardfile +15 -0
- data/LICENSE.md +41 -0
- data/Procfile +1 -0
- data/README.md +59 -0
- data/Rakefile +12 -0
- data/lib/provedores.yml +11 -0
- data/lib/rnfse/api/abrasf_1_0/definitions.json +374 -0
- data/lib/rnfse/api/abrasf_1_0/recepcionar_lote_rps.json +46 -0
- data/lib/rnfse/api/abrasf_1_0.rb +55 -0
- data/lib/rnfse/api/iss_net_1_0.rb +6 -0
- data/lib/rnfse/api.rb +101 -0
- data/lib/rnfse/configuration.rb +18 -0
- data/lib/rnfse/core.rb +9 -0
- data/lib/rnfse/hash.rb +148 -0
- data/lib/rnfse/string.rb +36 -0
- data/lib/rnfse/version.rb +3 -0
- data/lib/rnfse/xml_builder/abrasf_1_0.rb +95 -0
- data/lib/rnfse/xml_builder/iss_net_1_0.rb +70 -0
- data/lib/rnfse/xml_builder.rb +10 -0
- data/lib/rnfse.rb +22 -0
- data/rnfse.gemspec +60 -0
- data/spec/api/abrasf_1_0/recepcionar_lote_rps_json_spec.rb +123 -0
- data/spec/api/abrasf_1_0_spec.rb +26 -0
- data/spec/api/iss_net_1_0_spec.rb +99 -0
- data/spec/api_spec.rb +65 -0
- data/spec/core_spec.rb +35 -0
- data/spec/fixtures/abrasf_1_0/enviar_lote_rps_envio.xml +47 -0
- data/spec/fixtures/abrasf_1_0/nfse.xsd +771 -0
- data/spec/fixtures/certificate.pem +18 -0
- data/spec/fixtures/iss_net_1_0/enviar_lote_rps_envio.xml +75 -0
- data/spec/fixtures/key.pem +15 -0
- data/spec/fixtures/vcr_cassettes/iss_net_1_0_recepcionar_lote_rps.yml +214 -0
- data/spec/hash_spec.rb +205 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/string_spec.rb +38 -0
- data/spec/support/.keep +0 -0
- data/spec/version_spec.rb +5 -0
- data/spec/xml_builder/abrasf_1_0_spec.rb +63 -0
- data/spec/xml_builder/iss_net_1_0_spec.rb +86 -0
- data/spec/xml_builder_spec.rb +14 -0
- metadata +433 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'json-schema'
|
3
|
+
|
4
|
+
module Rnfse::API::Abrasf10
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
def recepcionar_lote_rps(hash = {})
|
9
|
+
file = get_filepath('recepcionar_lote_rps.json')
|
10
|
+
json = Rnfse::Hash.camelize_and_symbolize_keys(hash, false).to_json
|
11
|
+
errors = JSON::Validator.fully_validate(file, json)
|
12
|
+
if errors.empty?
|
13
|
+
xml = xml_builder.build_recepcionar_lote_rps_xml(hash)
|
14
|
+
xml.sign!(certificate: File.read(self.certificate), key: File.read(self.key))
|
15
|
+
response = self.soap_client.call(
|
16
|
+
:recepcionar_lote_rps,
|
17
|
+
soap_action: 'RecepcionarLoteRps',
|
18
|
+
message_tag: 'RecepcionarLoteRps',
|
19
|
+
message: { :'xml!' => "<![CDATA[#{xml}]]>" })
|
20
|
+
parse_response(response)
|
21
|
+
else
|
22
|
+
raise ArgumentError, errors, caller
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_response(response)
|
29
|
+
hash = Rnfse::Hash.new(response.body)
|
30
|
+
lote_rps_response = hash[:recepcionar_lote_rps_response]
|
31
|
+
if !lote_rps_response.empty? and lote_rps_response[:recepcionar_lote_rps_result]
|
32
|
+
xml = hash[:recepcionar_lote_rps_response][:recepcionar_lote_rps_result]
|
33
|
+
hash[:recepcionar_lote_rps_response][:recepcionar_lote_rps_result] =
|
34
|
+
Nori.new.parse(xml)
|
35
|
+
end
|
36
|
+
hash.underscore_and_symbolize_keys
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_filepath(filename)
|
40
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'abrasf_1_0', filename)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
extend ClassMethods
|
46
|
+
|
47
|
+
def self.extended(base)
|
48
|
+
base.extend(ClassMethods)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.included(base)
|
52
|
+
base.send(:include, ClassMethods)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/rnfse/api.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Rnfse
|
4
|
+
|
5
|
+
class API
|
6
|
+
attr_accessor :namespace
|
7
|
+
attr_accessor :endpoint
|
8
|
+
attr_accessor :api
|
9
|
+
attr_accessor :certificate
|
10
|
+
attr_accessor :key
|
11
|
+
attr_accessor :xml_builder
|
12
|
+
attr_accessor :soap_client
|
13
|
+
attr_accessor :verbose
|
14
|
+
|
15
|
+
def initialize(options = {})
|
16
|
+
options = load_options(options)
|
17
|
+
|
18
|
+
file = Pathname.new(File.expand_path('../..', __FILE__))
|
19
|
+
provedores = YAML.load_file(file.join('provedores.yml'))
|
20
|
+
|
21
|
+
case
|
22
|
+
when has_options(options, 'provedor', 'homologacao')
|
23
|
+
provedor = provedores['homologacao'][options['provedor'].to_s]
|
24
|
+
raise ArgumentError, 'provedor de homologação inexistente', caller if provedor.nil?
|
25
|
+
self.namespace = provedor['namespace']
|
26
|
+
self.endpoint = provedor['endpoint']
|
27
|
+
self.api = provedor['api']
|
28
|
+
|
29
|
+
when has_options(options, 'provedor', 'municipio')
|
30
|
+
provedor = provedores['producao'][options['provedor'].to_s]
|
31
|
+
raise ArgumentError, 'provedor inexistente', caller if provedor.nil?
|
32
|
+
self.namespace = provedor['namespace']
|
33
|
+
self.endpoint = provedor['endpoint'] % { municipio: options['municipio'] }
|
34
|
+
self.api = provedor['api']
|
35
|
+
|
36
|
+
when has_options(options, 'padrao', 'namespace', 'endpoint')
|
37
|
+
self.namespace = options['namespace'].to_s
|
38
|
+
self.endpoint = options['endpoint'].to_s
|
39
|
+
self.api = options['padrao'].to_s
|
40
|
+
|
41
|
+
else
|
42
|
+
raise ArgumentError, 'opções inválidas', caller
|
43
|
+
end
|
44
|
+
|
45
|
+
if has_options(options, 'certificate', 'key')
|
46
|
+
self.certificate = options['certificate']
|
47
|
+
self.key = options['key']
|
48
|
+
else
|
49
|
+
raise ArgumentError, 'opções de assinatura digital faltando', caller
|
50
|
+
end
|
51
|
+
|
52
|
+
self.verbose = options['verbose'] || false
|
53
|
+
self.xml_builder = options['xml_builder'] || XMLBuilder.new(padrao: self.api)
|
54
|
+
self.soap_client = options['soap_client'] || savon_client
|
55
|
+
|
56
|
+
extend self.class.const_get(String.camelize(self.api))
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def savon_client
|
62
|
+
savon_hash = {
|
63
|
+
soap_version: 2,
|
64
|
+
env_namespace: :soap,
|
65
|
+
namespace_identifier: nil,
|
66
|
+
ssl_verify_mode: :peer,
|
67
|
+
ssl_cert_file: self.certificate,
|
68
|
+
ssl_cert_key_file: self.key,
|
69
|
+
endpoint: self.endpoint,
|
70
|
+
namespace: self.namespace
|
71
|
+
}
|
72
|
+
|
73
|
+
savon_hash = savon_hash.merge(
|
74
|
+
log: true,
|
75
|
+
log_level: :debug,
|
76
|
+
pretty_print_xml: true
|
77
|
+
) if self.verbose
|
78
|
+
|
79
|
+
Savon.client(savon_hash)
|
80
|
+
end
|
81
|
+
|
82
|
+
def has_options(hash, *options)
|
83
|
+
options.each { |option| return false if hash[option].nil? }
|
84
|
+
end
|
85
|
+
|
86
|
+
def load_options(hash)
|
87
|
+
hash = Rnfse::Hash.new(hash)
|
88
|
+
hash = hash.stringify_keys
|
89
|
+
config = Rnfse::Configuration.instance
|
90
|
+
|
91
|
+
attrs = ['provedor', 'municipio', 'namespace', 'endpoint',
|
92
|
+
'verbose', 'api', 'certificate', 'key', 'xml_builder',
|
93
|
+
'soap_client', 'verbose', 'homologacao']
|
94
|
+
attrs.each do |attr|
|
95
|
+
hash[attr] = config.send(attr) if hash[attr].nil?
|
96
|
+
end
|
97
|
+
hash
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rnfse
|
2
|
+
class Configuration
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
attr_accessor :provedor
|
6
|
+
attr_accessor :municipio
|
7
|
+
attr_accessor :namespace
|
8
|
+
attr_accessor :endpoint
|
9
|
+
attr_accessor :homologacao
|
10
|
+
attr_accessor :api
|
11
|
+
attr_accessor :certificate
|
12
|
+
attr_accessor :key
|
13
|
+
attr_accessor :xml_builder
|
14
|
+
attr_accessor :soap_client
|
15
|
+
attr_accessor :verbose
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/rnfse/core.rb
ADDED
data/lib/rnfse/hash.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Rnfse
|
4
|
+
class Hash < ::Hash
|
5
|
+
|
6
|
+
def initialize(constructor = {})
|
7
|
+
if constructor.is_a?(::Hash)
|
8
|
+
super()
|
9
|
+
update(constructor)
|
10
|
+
else
|
11
|
+
super(constructor)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(other_hash)
|
16
|
+
if other_hash.is_a?(Hash)
|
17
|
+
super(other_hash)
|
18
|
+
else
|
19
|
+
other_hash.to_hash.each_pair do |key, value|
|
20
|
+
self[key] = value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.stringify_keys(obj)
|
26
|
+
self.transform_keys(obj) { |key| key.to_s rescue key }
|
27
|
+
end
|
28
|
+
|
29
|
+
def stringify_keys
|
30
|
+
self.class.stringify_keys(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.symbolize_keys(obj)
|
34
|
+
self.transform_keys(obj) { |key| key.to_sym rescue key }
|
35
|
+
end
|
36
|
+
|
37
|
+
def symbolize_keys
|
38
|
+
self.class.symbolize_keys(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.camelize_and_symbolize_keys(obj, uppercase_first_letter = true)
|
42
|
+
self.transform_keys(obj) do |key|
|
43
|
+
String.camelize(key.to_s, uppercase_first_letter).to_sym rescue key
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def camelize_and_symbolize_keys(uppercase_first_letter = true)
|
48
|
+
self.class.camelize_and_symbolize_keys(self, uppercase_first_letter)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.underscore_and_symbolize_keys(obj)
|
52
|
+
self.transform_keys(obj) do |key|
|
53
|
+
String.underscore(key.to_s).to_sym rescue key
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def underscore_and_symbolize_keys
|
58
|
+
self.class.underscore_and_symbolize_keys(self)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.transform_keys(obj, &block)
|
62
|
+
case
|
63
|
+
when obj.kind_of?(::Hash)
|
64
|
+
result = {}
|
65
|
+
obj.each_key do |key|
|
66
|
+
result[yield(key)] = self.transform_keys(obj[key], &block)
|
67
|
+
end
|
68
|
+
result
|
69
|
+
when obj.kind_of?(::Array)
|
70
|
+
result = []
|
71
|
+
obj.each do |elem|
|
72
|
+
result << self.transform_keys(elem, &block)
|
73
|
+
end
|
74
|
+
result
|
75
|
+
else
|
76
|
+
obj
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def transform_keys(&block)
|
81
|
+
self.class.transform_keys(self, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.transform_values(obj, key, &block)
|
85
|
+
key = /\A#{key}\Z/ unless key.kind_of?(::Regexp)
|
86
|
+
|
87
|
+
case
|
88
|
+
when obj.kind_of?(::Hash)
|
89
|
+
result = {}
|
90
|
+
obj.each_key do |k|
|
91
|
+
if key.match(k)
|
92
|
+
result[k] = yield(obj[k])
|
93
|
+
else
|
94
|
+
result[k] = self.transform_values(obj[k], key, &block)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
result
|
98
|
+
when obj.kind_of?(::Array)
|
99
|
+
result = []
|
100
|
+
obj.each do |elem|
|
101
|
+
result << self.transform_values(elem, key, &block)
|
102
|
+
end
|
103
|
+
result
|
104
|
+
else
|
105
|
+
obj
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def transform_values(key, &block)
|
110
|
+
self.class.transform_values(self, key, &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
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/
|
117
|
+
|
118
|
+
case
|
119
|
+
when obj.kind_of?(::Hash)
|
120
|
+
result = {}
|
121
|
+
obj.each_key do |k|
|
122
|
+
case
|
123
|
+
when (regex.match(k) and childs.empty?)
|
124
|
+
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)
|
127
|
+
else
|
128
|
+
result[k] = self.replace_key_values(obj[k], key, &block)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
result
|
132
|
+
when obj.kind_of?(::Array)
|
133
|
+
result = []
|
134
|
+
obj.each do |elem|
|
135
|
+
result << self.replace_key_values(elem, key, &block)
|
136
|
+
end
|
137
|
+
result
|
138
|
+
else
|
139
|
+
obj
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def replace_key_values(key, &block)
|
144
|
+
self.class.replace_key_values(self, key, &block)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
data/lib/rnfse/string.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Rnfse
|
4
|
+
class String < ::String
|
5
|
+
def self.camelize(term, uppercase_first_letter = true)
|
6
|
+
string = term.to_s
|
7
|
+
if uppercase_first_letter
|
8
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
9
|
+
else
|
10
|
+
string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
11
|
+
end
|
12
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { $2.capitalize }
|
13
|
+
string.gsub!('/', '::')
|
14
|
+
string
|
15
|
+
end
|
16
|
+
|
17
|
+
def camelize
|
18
|
+
self.class.camelize(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.underscore(term)
|
22
|
+
word = term.to_s.gsub('::', '/')
|
23
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(?=\b|[^a-z])/)
|
24
|
+
#{ "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
25
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
26
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
27
|
+
word.tr!("-", "_")
|
28
|
+
word.downcase!
|
29
|
+
word
|
30
|
+
end
|
31
|
+
|
32
|
+
def underscore
|
33
|
+
self.class.underscore(self)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Rnfse::XMLBuilder::Abrasf10
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
def build_recepcionar_lote_rps_xml(hash = {})
|
8
|
+
hash = prepare_hash(hash)
|
9
|
+
inner_xml = ::Gyoku.xml(hash, key_converter: :none)
|
10
|
+
xml_builder('EnviarLoteRpsEnvio', inner_xml).doc
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# prepara um hash para ser convertido a xml com o Gyoku
|
16
|
+
def prepare_hash(hash)
|
17
|
+
hash = camelize_hash(hash)
|
18
|
+
hash = wrap_rps(hash)
|
19
|
+
hash = add_tc_namespace(hash)
|
20
|
+
hash = clean_numerics(hash)
|
21
|
+
hash = date_to_utc(hash)
|
22
|
+
hash = fix_booleans(hash)
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
|
26
|
+
# converte booleanos para 1 ou 2
|
27
|
+
def fix_booleans(hash)
|
28
|
+
regex = /(IssRetido|OptanteSimplesNacional|IncentivadorCultural)\Z/
|
29
|
+
Rnfse::Hash.transform_values(hash, regex) do |val|
|
30
|
+
val ? 1 : 2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# converte datas para GMT-0
|
35
|
+
def date_to_utc(hash)
|
36
|
+
Rnfse::Hash.transform_values(hash, /DataEmissao\Z/) do |val|
|
37
|
+
DateTime.parse(val).new_offset(0).strftime('%FT%T')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# limpa tags que por precaução é melhor só conter números
|
42
|
+
def clean_numerics(hash)
|
43
|
+
regex = /(Cep|Cnae|Cpf|Cnpj)\Z/
|
44
|
+
Rnfse::Hash.transform_values(hash, regex) { |val| val.gsub(/\D/, '') }
|
45
|
+
end
|
46
|
+
|
47
|
+
# converte as chaves do hash para CamelCase
|
48
|
+
def camelize_hash(hash)
|
49
|
+
Rnfse::Hash.camelize_and_symbolize_keys(hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
# encapsula as rps dentro de listaRps com Rps/InfRps
|
53
|
+
def wrap_rps(hash)
|
54
|
+
hash[:LoteRps][:ListaRps] = {
|
55
|
+
:Rps => { :InfRps => hash[:LoteRps][:ListaRps] }
|
56
|
+
}
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
|
60
|
+
# adiciona o namespace tc nas tags dentro de loteRps
|
61
|
+
def add_tc_namespace(hash)
|
62
|
+
hash[:LoteRps] = Rnfse::Hash.transform_keys(hash[:LoteRps]) { |key| "tc:#{key}".to_sym }
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def xmlns
|
67
|
+
'http://www.abrasf.org.br/servico_enviar_lote_rps_envio.xsd'
|
68
|
+
end
|
69
|
+
|
70
|
+
# namespace dos tipos complexos
|
71
|
+
def xmlns_tc
|
72
|
+
'http://www.abrasf.org.br/tipos_complexos.xsd'
|
73
|
+
end
|
74
|
+
|
75
|
+
# instancia o builder a ser utilizado na geracao do xml
|
76
|
+
def xml_builder(root, inner_xml)
|
77
|
+
Nokogiri::XML::Builder.new(encoding: 'utf-8') do |xml|
|
78
|
+
xml.send(root.to_sym, 'xmlns' => xmlns, 'xmlns:tc' => xmlns_tc) do
|
79
|
+
xml << inner_xml
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
extend ClassMethods
|
86
|
+
|
87
|
+
def self.extended(base)
|
88
|
+
base.extend(ClassMethods)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.included(base)
|
92
|
+
base.send(:include, ClassMethods)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Rnfse::XMLBuilder::IssNet10
|
4
|
+
include Rnfse::XMLBuilder::Abrasf10
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
# prepara um hash para ser convertido a xml com o Gyoku
|
9
|
+
def prepare_hash(hash)
|
10
|
+
hash = camelize_hash(hash)
|
11
|
+
hash = wrap_rps(hash)
|
12
|
+
hash = add_tc_namespace(hash)
|
13
|
+
hash = clean_numerics(hash)
|
14
|
+
hash = date_to_utc(hash)
|
15
|
+
hash = fix_booleans(hash)
|
16
|
+
hash = wrap_cpf_cnpj(hash)
|
17
|
+
hash = add_municipio_prestacao_servico(hash)
|
18
|
+
hash = add_estado(hash)
|
19
|
+
hash = add_cidade(hash)
|
20
|
+
hash = alter_aliquota(hash)
|
21
|
+
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
# alterar o formato da aliquota de 0 a 1 para 0 a 100
|
26
|
+
def alter_aliquota(hash)
|
27
|
+
Rnfse::Hash.transform_values(hash, 'tc:Aliquota') do |val|
|
28
|
+
"%.2f" % (val * 100)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# troca a tag Endereco/CodigoMunicipio por Cidade
|
33
|
+
def add_cidade(hash)
|
34
|
+
Rnfse::Hash.replace_key_values(hash, 'tc:Endereco/tc:CodigoMunicipio') do |key, value|
|
35
|
+
{ 'tc:Cidade' => value }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# troca a tag Uf pela tag Estado
|
40
|
+
def add_estado(hash)
|
41
|
+
Rnfse::Hash.replace_key_values(hash, 'tc:Uf') do |key, value|
|
42
|
+
{ :'tc:Estado' => value }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# troca a tag CodigoMunicipio para MunicipioPrestacaoServico
|
47
|
+
# na tag Servico
|
48
|
+
def add_municipio_prestacao_servico(hash)
|
49
|
+
Rnfse::Hash.replace_key_values(hash, 'tc:Servico/tc:CodigoMunicipio') do |key, value|
|
50
|
+
{ :'tc:MunicipioPrestacaoServico' => value }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# encapsula as tags cpf ou cnpj em uma tag cpfcnpj
|
55
|
+
def wrap_cpf_cnpj(hash)
|
56
|
+
regex = /(Cpf|Cnpj)\Z/
|
57
|
+
Rnfse::Hash.replace_key_values(hash, regex) do |key, value|
|
58
|
+
{ :'tc:CpfCnpj' => { key => value } }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def xmlns
|
63
|
+
'http://www.issnetonline.com.br/webserviceabrasf/vsd/servico_enviar_lote_rps_envio.xsd'
|
64
|
+
end
|
65
|
+
|
66
|
+
def xmlns_tc
|
67
|
+
'http://www.issnetonline.com.br/webserviceabrasf/vsd/tipos_complexos.xsd'
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/lib/rnfse.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
require 'json'
|
5
|
+
require 'json-schema'
|
6
|
+
require 'gyoku'
|
7
|
+
require 'nokogiri-xmlsec1'
|
8
|
+
require 'savon'
|
9
|
+
|
10
|
+
require 'rnfse/core'
|
11
|
+
require 'rnfse/version'
|
12
|
+
require 'rnfse/configuration'
|
13
|
+
require 'rnfse/hash'
|
14
|
+
require 'rnfse/string'
|
15
|
+
|
16
|
+
require 'rnfse/api'
|
17
|
+
require 'rnfse/api/abrasf_1_0'
|
18
|
+
require 'rnfse/api/iss_net_1_0'
|
19
|
+
|
20
|
+
require 'rnfse/xml_builder'
|
21
|
+
require 'rnfse/xml_builder/abrasf_1_0'
|
22
|
+
require 'rnfse/xml_builder/iss_net_1_0'
|
data/rnfse.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'rnfse/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = 'rnfse'
|
10
|
+
s.version = Rnfse::VERSION
|
11
|
+
s.summary = %q{Biblioteca para a API de Nota Fiscal de Serviços
|
12
|
+
eletrônica (NFS-e) da ABRASF.}
|
13
|
+
s.description = %q{Biblioteca para integração com as várias implementações
|
14
|
+
municipais de Nota Fiscal de Serviços eletrônica (NFS-e) que utilizam uma
|
15
|
+
das versões ou variações dos padrões
|
16
|
+
[ABRASF](http://www.abrasf.org.br/paginas_multiplas_detalhes.php?cod_pagina=1).}
|
17
|
+
|
18
|
+
s.required_ruby_version = '>= 1.9.3'
|
19
|
+
|
20
|
+
s.licenses = ['MIT', 'GPL-3']
|
21
|
+
|
22
|
+
s.authors = ['Renan Mendes Carvalho']
|
23
|
+
s.email = ['aitherios@gmail.com']
|
24
|
+
s.homepage = 'https://github.com/aitherios/rnfse'
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split($/)
|
27
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
28
|
+
s.require_paths = ['lib']
|
29
|
+
s.rubyforge_project = '[none]'
|
30
|
+
|
31
|
+
s.add_dependency 'json', '~> 1.0'
|
32
|
+
s.add_dependency 'json-schema', '~> 2.0'
|
33
|
+
s.add_dependency 'gyoku', '~> 1.0'
|
34
|
+
s.add_dependency 'nokogiri-xmlsec1', '~> 0.0.7'
|
35
|
+
s.add_dependency 'savon', '~> 2.0'
|
36
|
+
|
37
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
38
|
+
s.add_development_dependency 'rake', '~> 10.0'
|
39
|
+
s.add_development_dependency 'rdoc', '~> 4.0'
|
40
|
+
s.add_development_dependency 'gem-release', '~> 0.7.0'
|
41
|
+
s.add_development_dependency 'rspec', '~> 3.0.0'
|
42
|
+
s.add_development_dependency 'rspec-its', '~> 1.0.0'
|
43
|
+
s.add_development_dependency 'simplecov', '~> 0.7.0'
|
44
|
+
s.add_development_dependency 'codeclimate-test-reporter', '>= 0'
|
45
|
+
s.add_development_dependency 'equivalent-xml', '~> 0.4.0'
|
46
|
+
s.add_development_dependency 'wwtd', '~> 0.5.0'
|
47
|
+
s.add_development_dependency 'vcr', '~> 2.9'
|
48
|
+
s.add_development_dependency 'webmock', '~> 1.0'
|
49
|
+
s.add_development_dependency 'guard', '~> 2.6.0'
|
50
|
+
s.add_development_dependency 'guard-rspec', '~> 4.2.0'
|
51
|
+
s.add_development_dependency 'guard-bundler', '~> 2.0.0'
|
52
|
+
s.add_development_dependency 'foreman', '~> 0.74.0'
|
53
|
+
s.add_development_dependency 'pry', '~> 0.10'
|
54
|
+
if RUBY_VERSION.to_i < 2
|
55
|
+
s.add_development_dependency 'pry-debugger', '~> 0.2'
|
56
|
+
else
|
57
|
+
s.add_development_dependency 'pry-byebug', '~> 1.0'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|