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
         |