biro 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +21 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +72 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +11 -0
  11. data/bin/setup +8 -0
  12. data/biro.gemspec +34 -0
  13. data/lib/biro/configuration.rb +28 -0
  14. data/lib/biro/gateways/bacen/request.rb +54 -0
  15. data/lib/biro/gateways/bacen/response.rb +109 -0
  16. data/lib/biro/gateways/bacen.rb +2 -0
  17. data/lib/biro/gateways/base_request.rb +30 -0
  18. data/lib/biro/gateways/base_response.rb +5 -0
  19. data/lib/biro/gateways/bvs/builders/base_builder.rb +17 -0
  20. data/lib/biro/gateways/bvs/builders/debits_request_builder.rb +26 -0
  21. data/lib/biro/gateways/bvs/builders/debits_response_builder.rb +45 -0
  22. data/lib/biro/gateways/bvs/builders/score_request_builder.rb +24 -0
  23. data/lib/biro/gateways/bvs/builders/score_response_builder.rb +93 -0
  24. data/lib/biro/gateways/bvs/request.rb +71 -0
  25. data/lib/biro/gateways/bvs/response.rb +56 -0
  26. data/lib/biro/gateways/bvs.rb +7 -0
  27. data/lib/biro/gateways/cred_defense/request.rb +69 -0
  28. data/lib/biro/gateways/cred_defense/response.rb +131 -0
  29. data/lib/biro/gateways/cred_defense.rb +2 -0
  30. data/lib/biro/gateways/midia100/request.rb +59 -0
  31. data/lib/biro/gateways/midia100/response.rb +166 -0
  32. data/lib/biro/gateways/midia100.rb +2 -0
  33. data/lib/biro/gateways/ph3a/builders/login_builder.rb +15 -0
  34. data/lib/biro/gateways/ph3a/request.rb +72 -0
  35. data/lib/biro/gateways/ph3a/response.rb +340 -0
  36. data/lib/biro/gateways/ph3a.rb +3 -0
  37. data/lib/biro/gateways/spc/request.rb +59 -0
  38. data/lib/biro/gateways/spc/response.rb +190 -0
  39. data/lib/biro/gateways/spc.rb +2 -0
  40. data/lib/biro/gateways.rb +8 -0
  41. data/lib/biro/response.rb +15 -0
  42. data/lib/biro/utils/soap.rb +27 -0
  43. data/lib/biro/utils.rb +11 -0
  44. data/lib/biro/version.rb +3 -0
  45. data/lib/biro.rb +31 -0
  46. metadata +206 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 135d5ac51a23bb35aca3360514eddf2e521c0e51
4
+ data.tar.gz: 21c7baa69660e28d4dcd9517ae053d1b2477943a
5
+ SHA512:
6
+ metadata.gz: 7f5663620edd64e7966c6e6d90f76b931c403f2d653d75bdd450d3bd4b9c4f62becfe5b10b986eab7c775b93ac3e0896e541cb497ede07b3e74aa68341b0df7f
7
+ data.tar.gz: 19132771a0be56c500cd6cd1991f6df3dcbb2a64a3580b50bec40c694ede1f2e271bfbd549878623c0a6bcf8f85ee5ad984339ab7bebb49e533105fb882db64a
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in biro.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Noverde
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Noverde
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Biro
2
+
3
+ DISCLAIMER: This library is currently in alpha and under active development.
4
+
5
+ Biro is an extraction from the [Noverde](https://www.noverde.com.br) credit analysis system. Noverde's requirements for a simple and unified
6
+ API to access different credit bureaus (pronounced "Birô" in brazilian portuguese) and others third parties systems was the main motivation to
7
+ build this library.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'biro'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install biro
24
+
25
+ ## Usage
26
+
27
+ ```ruby
28
+ require 'biro'
29
+
30
+ # Configure the gateway provider
31
+ Biro.configure do |config|
32
+ config.gateway :spc, username: 'myusername', password: 'mypassword'
33
+ end
34
+
35
+ # Use the gateway provider to fetch user data (the attributes are explained below)
36
+ response = Biro.gateways[:spc].find('99353932750', 'F', 495)
37
+
38
+ # Use the return data
39
+ response[:resultado][:consumidor] # => should return the person data
40
+ ```
41
+
42
+ ## Gateways
43
+
44
+ ### [SPC](https://www.spcbrasil.org.br)
45
+ ```ruby
46
+ Biro.configure do |config|
47
+ config.gateway :spc, username: 'myusername', password: 'mypassword'
48
+ end
49
+ ```
50
+
51
+ #### display_products
52
+ This method wraps the "listarProdutos" from the SOAP API. You need this method to get the **product code**.
53
+ ```ruby
54
+ Biro.gateways[:spc].display_products
55
+ ```
56
+
57
+ #### find(document, kind, product_code, options = {})
58
+ This method wraps the "consultar" from the SOAP API. You should input the CPF if the kind is F or the CNPJ if the person is J.
59
+ You can put the **include_score: true** to get the credit score data.
60
+
61
+ ```ruby
62
+ Biro.gateways[:spc].find('80541028286', 'F', 455, include_score: true)
63
+ ```
64
+
65
+ ## Contributing
66
+
67
+ Bug reports and pull requests are welcome on GitHub at https://github.com/noverde/biro.
68
+
69
+
70
+ ## License
71
+
72
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "biro"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/biro.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'biro/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "biro"
8
+ spec.version = Biro::VERSION
9
+ spec.authors = ["Noverde Team", "Rafael Izidoro", "Alexandre Santos", "Paulo Herrera"]
10
+ spec.email = ["dev@noverde.com.br", "izidoro.rafa@gmail.com", "alexandre.sns@gmail.com", "pauloherreralopes@gmail.com"]
11
+
12
+ spec.summary = %q{Biro is a library that standardizes multi-provider brazilian credit bureaus.}
13
+ spec.description = %q{Biro is a library that standardizes multi-provider brazilian credit bureaus.}
14
+ spec.homepage = "https://github.com/noverde/biro"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+
25
+ spec.add_dependency "savon", "~> 2.11"
26
+ spec.add_dependency "rest-client", "~> 2.0"
27
+ spec.add_dependency "activesupport", '~> 5.0'
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.13"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec", "~> 3.0"
32
+ spec.add_development_dependency "pry-byebug", "~> 3.4"
33
+ spec.add_development_dependency 'webmock', '~> 2.3'
34
+ end
@@ -0,0 +1,28 @@
1
+ require 'singleton'
2
+
3
+ module Biro
4
+ class Configuration
5
+ include Singleton
6
+
7
+ attr_accessor :environment, :logger
8
+
9
+ def logger
10
+ @logger ||= Logger.new(STDOUT)
11
+ end
12
+
13
+ def development!
14
+ @environment = :development
15
+ end
16
+
17
+ def development?
18
+ @environment == :development
19
+ end
20
+
21
+ def gateway(name, options = {})
22
+ klass_name = Biro::Utils.camelize(name.to_s) + '::Request'
23
+ klass = Biro.const_get(klass_name)
24
+
25
+ Biro.gateways[name] = klass.new(options)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ module Biro
2
+ module Bacen
3
+ class Request < BaseRequest
4
+ include Utils::Soap
5
+
6
+ def development_url
7
+ 'https://scr.bcb.gov.br/wsscr/ControleCliente.xml'
8
+ end
9
+
10
+ def production_url
11
+ 'https://scr.bcb.gov.br/wsscr/ControleCliente.xml'
12
+ end
13
+
14
+ def required_params
15
+ [:username, :password]
16
+ end
17
+
18
+ def find(document, date)
19
+ begin
20
+ params = {}
21
+ get_parameters(params, document, date)
22
+ result = soap.call(:get_resumo_do_cliente, message: params)
23
+ rescue => e
24
+ Biro.log(:warn, "Unable to process Bacen request")
25
+ raise StandardError.new("Error at Bacen request: #{e.message}")
26
+ end
27
+
28
+ get_response result
29
+ end
30
+
31
+ private
32
+
33
+ def get_response(result)
34
+ response = Response.new(result)
35
+ raise DocumentNotFoundError.new("Document not found: Code => #{response.result_validation[:codigo]} and Message => #{response.result_validation[:mensagem]}") if ['55'].include?(response.result_validation[:codigo])
36
+ raise AuthenticationError.new("Authentication Error: Code => #{response.result_validation[:codigo]} and Message => #{response.result_validation[:mensagem]}") if ['62','63','53'].include?(response.result_validation[:codigo])
37
+ raise StandardError.new("Error at Bacen Request: Code => #{response.result_validation[:codigo]} and Message => #{response.result_validation[:mensagem]}") unless response.result_validation.blank? || ['50'].include?(response.result_validation[:codigo])
38
+
39
+ response
40
+ end
41
+
42
+ def savon_options
43
+ { basic_auth: [@username, @password], headers: { 'SOAPAction' => ''} }
44
+ end
45
+
46
+ def get_parameters(params, document, date)
47
+ params['codCliente'] = document
48
+ params['tpCliente'] = 1
49
+ params['dataBase'] = date
50
+ params['autorizacao'] = 'S'
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,109 @@
1
+ require 'active_support/core_ext/array'
2
+
3
+ module Biro
4
+ module Bacen
5
+ class Response < BaseResponse
6
+ def initialize(response)
7
+ @body = response.body
8
+ end
9
+
10
+ def cnpj_if
11
+ result.dig(:cnpj_da_if_solicitante)
12
+ end
13
+
14
+ def cpf
15
+ result.dig(:codigo_do_cliente)
16
+ end
17
+
18
+ def assumed_co_obligation
19
+ result.dig(:coobrigacao_assumida)&.to_f&.round(2)
20
+ end
21
+
22
+ def received_co_obligation
23
+ result.dig(:coobrigacao_recebida)&.to_f&.round(2)
24
+ end
25
+
26
+ def base_date
27
+ result.dig(:data_base_consultada)
28
+ end
29
+
30
+ def relationship_initial_date
31
+ result.dig(:data_inicio_relacionamento)&.to_date
32
+ end
33
+
34
+ def invoice_list
35
+ return if operation_list.blank?
36
+
37
+ result.dig(:lista_de_resumo_das_operacoes).each do |item|
38
+ {
39
+ :variacao_cambial => item[:variacao_cambial],
40
+ :modalidade => item[:modalidade],
41
+ :lista_de_vencimentos => item[:lista_de_vencimentos] #TODO: Translate the invoice codes
42
+ }
43
+ end
44
+ end
45
+
46
+ def exchange_rate_variation
47
+ operation_list&.dig(:variacao_cambial)
48
+ end
49
+
50
+ def processed_documents_percentage
51
+ result.dig(:percentual_documentos_processados)&.to_f&.round(2)
52
+ end
53
+
54
+ def processed_volume_percentage
55
+ result.dig(:percentual_volume_processado)&.to_f&.round(2)
56
+ end
57
+
58
+ def institutions_amount
59
+ result.dig(:quantidade_de_instituicoes).to_i
60
+ end
61
+
62
+ def operation_amount
63
+ result.dig(:quantidade_de_operacoes).to_i
64
+ end
65
+
66
+ def unconformity_operation_amount
67
+ result.dig(:quantidade_operacoes_discordancia).to_i
68
+ end
69
+
70
+ def sub_judice_operation_amount
71
+ result.dig(:quantidade_operacoes_sub_judice).to_i
72
+ end
73
+
74
+ def unconformity_total_responsibility
75
+ result.dig(:responsabilidade_total_discordancia).to_i
76
+ end
77
+
78
+ def sub_judice_total_responsibility
79
+ result.dig(:responsabilidade_total_sub_judice).to_i
80
+ end
81
+
82
+ def indirect_risk
83
+ result.dig(:risco_indireto_vendor).to_i
84
+ end
85
+
86
+ def customer_type
87
+ result.dig(:tipo_do_cliente).to_i
88
+ end
89
+
90
+ def result_validation
91
+ validation_content = result.dig(:lista_de_mensagens_de_validacao)
92
+
93
+ return { } if validation_content.blank?
94
+
95
+ validation_content
96
+ end
97
+
98
+ private
99
+
100
+ def result
101
+ @body.dig(:get_resumo_do_cliente_response, :return)
102
+ end
103
+
104
+ def operation_list
105
+ result.dig(:lista_de_resumo_das_operacoes)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'bacen/request'
2
+ require_relative 'bacen/response'
@@ -0,0 +1,30 @@
1
+ module Biro
2
+ class BaseRequest
3
+ class AuthenticationError < StandardError; end
4
+ class DocumentNotFoundError < StandardError; end
5
+
6
+ def production_url
7
+ raise NotImplementedError.new('production_url must be implemented')
8
+ end
9
+
10
+ def development_url
11
+ production_url
12
+ end
13
+
14
+ def url
15
+ Biro.development? ? development_url : production_url
16
+ end
17
+
18
+ def required_params
19
+ []
20
+ end
21
+
22
+ def initialize(params)
23
+ required_params.each do |param|
24
+ raise ArgumentError.new("Missing required parameter '#{param}' for #{self.class.name}") unless params.has_key?(param)
25
+
26
+ instance_variable_set("@#{param}", params[param])
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ module Biro
2
+ class BaseResponse
3
+ attr_reader :body
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ class BaseBuilder
2
+ def initialize document, username, password
3
+ @document = document
4
+ @username = username
5
+ @password = password
6
+ end
7
+
8
+ def build
9
+ raise "This method must be implemented"
10
+ end
11
+
12
+ protected
13
+
14
+ def build_string
15
+ @parameters.values.map { |p| p[:type] == "T" ? p[:value].to_s.ljust(p[:size], " ") : p[:value].to_s.rjust(p[:size],"0") }.join
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'base_builder'
2
+
3
+ class DebitsRequestBuilder < BaseBuilder
4
+ def build
5
+ @parameters = {
6
+ transaction: { size: 8, type: "T", value: "CSR60" },
7
+ version: { size: 2, type: "T", value: "01" },
8
+ reserved_applicant: { size: 10, type: "T", value: "" },
9
+ reserved_bvs: { size: 20, type: "T", value: "" },
10
+ service_code: { size: 8, type: "N", value: @username },
11
+ password: { size: 8, type: "T", value: @password },
12
+ search_type: { size: 8, type: "T", value: "SPCIT" },
13
+ reserverd_bvs_2: { size: 4, type: "T", value: ""},
14
+ response_type: { size: 1, type: "T", value: "2" },
15
+ document_type: { size: 1, type: "T", value: "1" },
16
+ document: { size: 14, type: "N", value: @document },
17
+ reserverd_bvs_3: { size: 235, type: "T", value: ""},
18
+ facilitator_code: { size: 8, type: "N", value: "" },
19
+ reserverd_bvs_4: { size: 2, type: "T", value: ""},
20
+ response_trans_type: { size: 1, type: "T", value: "C" },
21
+ finish_marker: { size: 1, type: "T", value: "X" }
22
+ }
23
+
24
+ build_string
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ class DebitsResponseBuilder
2
+ def initialize body
3
+ @body = body.gsub("\n", '').scan(/<PRE>([^<>]*)<\/PRE>/imu).flatten[0]
4
+ end
5
+
6
+ def transaction
7
+ @body[0..7]
8
+ end
9
+
10
+ def version
11
+ @body[8..9]
12
+ end
13
+
14
+ def reserved_applicant
15
+ @body[10..19]
16
+ end
17
+
18
+ def reserved_bvs
19
+ @body[20..39]
20
+ end
21
+
22
+ def response_type
23
+ @body[56]
24
+ end
25
+
26
+ def return_code
27
+ @body[57]
28
+ end
29
+
30
+ def response_text_size
31
+ @body[58..61].to_i
32
+ end
33
+
34
+ def response_text
35
+ @body[62,response_text_size]
36
+ end
37
+
38
+ def error_message
39
+ response_text[8..100]
40
+ end
41
+
42
+ def debits_info
43
+ response_text[6]
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ class ScoreRequestBuilder < BaseBuilder
2
+ def build
3
+ @parameters = {
4
+ transaction: { size: 8, type: "T", value: "CSR60" },
5
+ version: { size: 2, type: "T", value: "01" },
6
+ reserved_applicant: { size: 10, type: "T", value: "" },
7
+ reserved_bvs: { size: 20, type: "T", value: "" },
8
+ service_code: { size: 8, type: "N", value: @username },
9
+ password: { size: 8, type: "T", value: @password },
10
+ search_type: { size: 8, type: "T", value: "SCORE" },
11
+ search_version: { size: 2, type: "T", value: "04" },
12
+ response_type: { size: 1, type: "T", value: "2" },
13
+ response_trans_type: { size: 1, type: "T", value: "C" },
14
+ document_type: { size: 1, type: "T", value: "1" },
15
+ document: { size: 14, type: "N", value: @document },
16
+ score_model: { size: 2, type: "T", value: "63" },
17
+ source_cep: { size: 8, type: "N", value: "" },
18
+ facilitator_code: { size: 8, type: "N", value: "" },
19
+ finish_marker: { size: 1, type: "T", value: "X" }
20
+ }
21
+
22
+ build_string
23
+ end
24
+ end
@@ -0,0 +1,93 @@
1
+ class ScoreResponseBuilder
2
+ def initialize body
3
+ @body = body.gsub("\n", '').scan(/<PRE>([^<>]*)<\/PRE>/imu).flatten[0]
4
+ end
5
+
6
+ def transaction
7
+ @body[0..7]
8
+ end
9
+
10
+ def version
11
+ @body[8..9]
12
+ end
13
+
14
+ def reserved_applicant
15
+ @body[10..19]
16
+ end
17
+
18
+ def reserved_bvs
19
+ @body[20..39]
20
+ end
21
+
22
+ def service_code
23
+ @body[40..47]
24
+ end
25
+
26
+ def search_type
27
+ @body[48..55]
28
+ end
29
+
30
+ def search_version
31
+ @body[56..57]
32
+ end
33
+
34
+ def response_type
35
+ @body[58]
36
+ end
37
+
38
+ def return_code
39
+ @body[59]
40
+ end
41
+
42
+ def search_number
43
+ @body[60..66]
44
+ end
45
+
46
+ def response_text_size
47
+ @body[67..70].to_i
48
+ end
49
+
50
+ def response_text
51
+ @body[71,response_text_size]
52
+ end
53
+
54
+ def response_text_init
55
+ response_text[0..2]
56
+ end
57
+
58
+ def response_text_type
59
+ response_text[3..5]
60
+ end
61
+
62
+ def response_text_is_present
63
+ response_text[6]
64
+ end
65
+
66
+ def response_text_document_type
67
+ response_text[7]
68
+ end
69
+
70
+ def response_text_document
71
+ response_text[8..21]
72
+ end
73
+
74
+ def response_text_name
75
+ response_text[22..136]
76
+ end
77
+
78
+ def response_text_result_score
79
+ response_text[137..140]
80
+ end
81
+
82
+ def response_text_description
83
+ response_text[141..160]
84
+ end
85
+
86
+ def response_text_over
87
+ response_text[160..500]
88
+ end
89
+
90
+ def error_message
91
+ response_text[8..100]
92
+ end
93
+ end