instant_quote 1.4.0 → 1.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40981c76f383ff34163f212e6b9f32a58d2281426ee40fc872b1f38102e24754
4
- data.tar.gz: 227f3b25eec82494a383ad796f09b0dda5ad9b1472d93c1ba6e2728855529c59
3
+ metadata.gz: c8a949bc8d63fd2ad95636f7a72ff7e8a9f801927eea13634681a20321abf0e5
4
+ data.tar.gz: 25822b27eabbe49c12a40dfd97b614c6d80d17c69ee83f48e0f20149264d4be8
5
5
  SHA512:
6
- metadata.gz: 860eb841f3405a3bf62c614551d0f663de38451956321ca2998d790381a365f42067f85d48bc32c90a689ed579e69d9167dbe32d9f2220292ad79a119227d730
7
- data.tar.gz: f767ccde890f42dfc727e230c0fc02479d81bcf0e911a1b00d33e12ac7679edd244cfe41be7e6dc7c5ad292796dae85379962b5b0643b1aa646817c19499ec14
6
+ metadata.gz: c42945fc752a43165f1c010974b1489095be672cacf42580d0ce7693e7fd27d147060d376e343f40ddc6399771e84824edf206fef853dba168433053a21611a4
7
+ data.tar.gz: cb94c2781c903afe2ae45e61dd1180ffa739752a2c604f42c01dd81fe6bb111b3ccd43168f21e0968c8b0f803c6f078ade80fffa524d1aaed2365dfd6fcb3095
data/.rubocop.yml CHANGED
@@ -1,3 +1,14 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+ NewCops: enable
4
+
5
+ require:
6
+ - rubocop-rake
7
+ - rubocop-rspec
8
+
9
+ Gemspec/RequiredRubyVersion:
10
+ Enabled: false
11
+
1
12
  Layout/LineLength:
2
13
  Max: 100
3
14
 
@@ -24,3 +35,6 @@ Style/HashTransformKeys:
24
35
 
25
36
  Style/HashTransformValues:
26
37
  Enabled: true
38
+
39
+ RSpec/MultipleExpectations:
40
+ Enabled: false
data/.travis.yml CHANGED
@@ -5,3 +5,6 @@ cache: bundler
5
5
  rvm:
6
6
  - 2.6.3
7
7
  before_install: gem install bundler -v 2.0.2
8
+ script:
9
+ - bundle exec rspec --fail-fast
10
+ - bundle exec rubocop
data/Gemfile.lock CHANGED
@@ -1,46 +1,50 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- instant_quote (1.4.0)
4
+ instant_quote (1.6.2)
5
5
  activesupport
6
6
  capital_on_tap
7
7
  iwoca
8
8
  money
9
9
  optimum
10
10
  phonelib
11
+ youlend
11
12
 
12
13
  GEM
13
14
  remote: https://rubygems.org/
14
15
  specs:
15
- activesupport (6.0.3.3)
16
+ activesupport (6.1.1)
16
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- zeitwerk (~> 2.2, >= 2.2.2)
18
+ i18n (>= 1.6, < 2)
19
+ minitest (>= 5.1)
20
+ tzinfo (~> 2.0)
21
+ zeitwerk (~> 2.3)
21
22
  addressable (2.7.0)
22
23
  public_suffix (>= 2.0.2, < 5.0)
23
- ast (2.4.0)
24
- byebug (11.1.1)
24
+ ast (2.4.2)
25
+ byebug (11.1.3)
25
26
  capital_on_tap (1.0.0)
26
27
  addressable
27
28
  faraday
28
29
  faraday_middleware
29
30
  multi_json
30
31
  rainbow
31
- coderay (1.1.2)
32
- concurrent-ruby (1.1.7)
33
- crack (0.4.3)
34
- safe_yaml (~> 1.0.0)
35
- diff-lcs (1.3)
36
- docile (1.3.2)
37
- dotenv (2.7.5)
38
- faraday (1.0.1)
32
+ coderay (1.1.3)
33
+ concurrent-ruby (1.1.8)
34
+ crack (0.4.5)
35
+ rexml
36
+ diff-lcs (1.4.4)
37
+ docile (1.3.5)
38
+ dotenv (2.7.6)
39
+ faraday (1.3.0)
40
+ faraday-net_http (~> 1.0)
39
41
  multipart-post (>= 1.2, < 3)
42
+ ruby2_keywords
43
+ faraday-net_http (1.0.1)
40
44
  faraday_middleware (1.0.0)
41
45
  faraday (~> 1.0)
42
46
  hashdiff (1.0.1)
43
- i18n (1.8.5)
47
+ i18n (1.8.8)
44
48
  concurrent-ruby (~> 1.0)
45
49
  iwoca (1.0.0)
46
50
  addressable
@@ -48,69 +52,84 @@ GEM
48
52
  faraday_middleware
49
53
  multi_json
50
54
  rainbow
51
- jaro_winkler (1.5.4)
52
55
  method_source (1.0.0)
53
- minitest (5.14.2)
54
- money (6.13.8)
56
+ minitest (5.14.3)
57
+ money (6.14.0)
55
58
  i18n (>= 0.6.4, <= 2)
56
59
  multi_json (1.15.0)
57
60
  multipart-post (2.1.1)
58
- optimum (1.0.0)
61
+ optimum (1.1.0)
59
62
  addressable
60
63
  faraday
61
64
  faraday_middleware
62
65
  multi_json
63
66
  rainbow
64
- parallel (1.19.1)
65
- parser (2.7.0.5)
66
- ast (~> 2.4.0)
67
- phonelib (0.6.45)
68
- pry (0.13.0)
67
+ parallel (1.20.1)
68
+ parser (3.0.0.0)
69
+ ast (~> 2.4.1)
70
+ phonelib (0.6.48)
71
+ pry (0.13.1)
69
72
  coderay (~> 1.1)
70
73
  method_source (~> 1.0)
71
74
  pry-byebug (3.9.0)
72
75
  byebug (~> 11.0)
73
76
  pry (~> 0.13.0)
74
- public_suffix (4.0.3)
77
+ public_suffix (4.0.6)
75
78
  rainbow (3.0.0)
76
79
  rake (10.5.0)
80
+ regexp_parser (2.0.3)
77
81
  rexml (3.2.4)
78
- rspec (3.9.0)
79
- rspec-core (~> 3.9.0)
80
- rspec-expectations (~> 3.9.0)
81
- rspec-mocks (~> 3.9.0)
82
- rspec-core (3.9.1)
83
- rspec-support (~> 3.9.1)
84
- rspec-expectations (3.9.1)
82
+ rspec (3.10.0)
83
+ rspec-core (~> 3.10.0)
84
+ rspec-expectations (~> 3.10.0)
85
+ rspec-mocks (~> 3.10.0)
86
+ rspec-core (3.10.1)
87
+ rspec-support (~> 3.10.0)
88
+ rspec-expectations (3.10.1)
85
89
  diff-lcs (>= 1.2.0, < 2.0)
86
- rspec-support (~> 3.9.0)
87
- rspec-mocks (3.9.1)
90
+ rspec-support (~> 3.10.0)
91
+ rspec-mocks (3.10.2)
88
92
  diff-lcs (>= 1.2.0, < 2.0)
89
- rspec-support (~> 3.9.0)
90
- rspec-support (3.9.2)
91
- rubocop (0.80.1)
92
- jaro_winkler (~> 1.5.1)
93
+ rspec-support (~> 3.10.0)
94
+ rspec-support (3.10.2)
95
+ rubocop (1.9.1)
93
96
  parallel (~> 1.10)
94
- parser (>= 2.7.0.1)
97
+ parser (>= 3.0.0.0)
95
98
  rainbow (>= 2.2.2, < 4.0)
99
+ regexp_parser (>= 1.8, < 3.0)
96
100
  rexml
101
+ rubocop-ast (>= 1.2.0, < 2.0)
97
102
  ruby-progressbar (~> 1.7)
98
- unicode-display_width (>= 1.4.0, < 1.7)
99
- ruby-progressbar (1.10.1)
100
- safe_yaml (1.0.5)
101
- simplecov (0.18.5)
103
+ unicode-display_width (>= 1.4.0, < 3.0)
104
+ rubocop-ast (1.4.1)
105
+ parser (>= 2.7.1.5)
106
+ rubocop-rake (0.5.1)
107
+ rubocop
108
+ rubocop-rspec (2.2.0)
109
+ rubocop (~> 1.0)
110
+ rubocop-ast (>= 1.1.0)
111
+ ruby-progressbar (1.11.0)
112
+ ruby2_keywords (0.0.4)
113
+ simplecov (0.21.2)
102
114
  docile (~> 1.1)
103
115
  simplecov-html (~> 0.11)
104
- simplecov-html (0.12.2)
105
- thread_safe (0.3.6)
106
- tzinfo (1.2.7)
107
- thread_safe (~> 0.1)
108
- unicode-display_width (1.6.1)
109
- webmock (3.8.3)
116
+ simplecov_json_formatter (~> 0.1)
117
+ simplecov-html (0.12.3)
118
+ simplecov_json_formatter (0.1.2)
119
+ tzinfo (2.0.4)
120
+ concurrent-ruby (~> 1.0)
121
+ unicode-display_width (2.0.0)
122
+ webmock (3.11.2)
110
123
  addressable (>= 2.3.6)
111
124
  crack (>= 0.3.2)
112
125
  hashdiff (>= 0.4.0, < 2.0.0)
113
- zeitwerk (2.4.0)
126
+ youlend (1.1.3)
127
+ addressable
128
+ faraday
129
+ faraday_middleware
130
+ multi_json
131
+ rainbow
132
+ zeitwerk (2.4.2)
114
133
 
115
134
  PLATFORMS
116
135
  ruby
@@ -123,8 +142,10 @@ DEPENDENCIES
123
142
  rake (~> 10.0)
124
143
  rspec (~> 3.0)
125
144
  rubocop
145
+ rubocop-rake
146
+ rubocop-rspec
126
147
  simplecov
127
148
  webmock
128
149
 
129
150
  BUNDLED WITH
130
- 2.1.4
151
+ 2.2.5
data/bin/console CHANGED
@@ -24,6 +24,12 @@ Iwoca.configure do |config|
24
24
  config.webhook_signature = ENV['IWOCA_WEBHOOK_SIGNATURE']
25
25
  end
26
26
 
27
+ Youlend.configure do |config|
28
+ config.client_id = ENV['YOULEND_CLIENT_ID']
29
+ config.client_secret = ENV['YOULEND_CLIENT_SECRET']
30
+ config.debug = true
31
+ end
32
+
27
33
  send(:include, InstantQuote)
28
34
 
29
35
  require 'pry'
@@ -6,6 +6,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
  require 'instant_quote/version'
7
7
 
8
8
  Gem::Specification.new do |spec|
9
+ spec.required_ruby_version = '>= 2.5.0'
9
10
  spec.name = 'instant_quote'
10
11
  spec.version = InstantQuote::VERSION
11
12
  spec.authors = ['rikas']
@@ -32,13 +33,16 @@ Gem::Specification.new do |spec|
32
33
  spec.add_development_dependency 'rake', '~> 10.0'
33
34
  spec.add_development_dependency 'rspec', '~> 3.0'
34
35
  spec.add_development_dependency 'rubocop'
36
+ spec.add_development_dependency 'rubocop-rake'
37
+ spec.add_development_dependency 'rubocop-rspec'
35
38
  spec.add_development_dependency 'simplecov'
36
39
  spec.add_development_dependency 'webmock'
37
40
 
38
41
  spec.add_dependency 'activesupport'
39
42
  spec.add_dependency 'capital_on_tap'
40
43
  spec.add_dependency 'iwoca'
41
- spec.add_dependency 'optimum'
42
44
  spec.add_dependency 'money'
45
+ spec.add_dependency 'optimum'
43
46
  spec.add_dependency 'phonelib'
47
+ spec.add_dependency 'youlend'
44
48
  end
data/lib/instant_quote.rb CHANGED
@@ -17,6 +17,7 @@ module InstantQuote
17
17
  get_link
18
18
  get_quote
19
19
  get_status
20
+ get_preapproval
20
21
  get_approval
21
22
  additional_fields
22
23
  parse_decision
@@ -26,6 +27,7 @@ module InstantQuote
26
27
  # InstantQuote.get_link(connection)
27
28
  # InstantQuote.get_quote(connection)
28
29
  # InstantQuote.get_status(connection)
30
+ # InstantQuote.get_preapproval(connection)
29
31
  # InstantQuote.get_approval(connection)
30
32
  # InstantQuote.additional_fields(connection)
31
33
  # InstantQuote.parse_decision(connection)
@@ -2,42 +2,63 @@
2
2
 
3
3
  module InstantQuote
4
4
  class Adapter
5
+ # This is one additional field that we always want to ask, since we're using it for phone
6
+ # validating the applicant.
7
+ DEFAULT_ADDIONAL_FIELDS = [
8
+ {
9
+ name: 'applicant_phone_number',
10
+ label: 'Applicant mobile phone',
11
+ required: true
12
+ }
13
+ ].freeze
14
+
5
15
  def self.additional_fields(fields = [])
6
- return (@additional_fields || []) if fields.empty?
16
+ return (@additional_fields || DEFAULT_ADDIONAL_FIELDS) if fields.empty?
17
+
18
+ @additional_fields ||= DEFAULT_ADDIONAL_FIELDS
19
+ @additional_fields += fields
20
+ end
7
21
 
8
- @additional_fields = fields
22
+ def self.get_link(connection)
23
+ new.get_link(connection)
9
24
  end
10
25
 
11
- def self.get_link(application_id)
12
- new.get_link(application_id)
26
+ def self.get_quote(params, connection = nil)
27
+ new.get_quote(params, connection)
13
28
  end
14
29
 
15
- def self.get_quote(params)
16
- new.get_quote(params)
30
+ def self.get_status(application_id, connection = nil)
31
+ new.get_status(application_id, connection)
17
32
  end
18
33
 
19
- def self.get_status(application_id)
20
- new.get_status(application_id)
34
+ def self.get_preapproval(params, connection = nil)
35
+ new.get_preapproval(params, connection)
21
36
  end
22
37
 
23
- def self.get_approval(application_id)
24
- new.get_approval(application_id)
38
+ def self.get_approval(application_id, connection = nil)
39
+ new.get_approval(application_id, connection)
25
40
  end
26
41
 
27
- def get_link(_application_id)
42
+ def get_link(_application_id, _connection = nil)
28
43
  raise NotImplementedError, "You must implement '#{self.class.name}#get_link'"
29
44
  end
30
45
 
31
- def get_quote(_params)
46
+ def get_quote(_params, _connection = nil)
32
47
  raise NotImplementedError, "You must implement '#{self.class.name}#get_quote'"
33
48
  end
34
49
 
35
- def get_status(_application_id)
50
+ def get_status(_application_id, _connection = nil)
36
51
  raise NotImplementedError, "You must implement '#{self.class.name}#get_status'"
37
52
  end
38
53
 
39
- def get_approval(_application_id)
40
- raise NotImplementedError, "You must implement '#{self.class.name}#get_approval"
54
+ # Default for pre approval will be true, override it in the adapter class if needed.
55
+ def get_preapproval(_params, _connection = nil)
56
+ true
57
+ end
58
+
59
+ # Default for approval will be true, override it in the adapter class if needed.
60
+ def get_approval(_application_id, _connection = nil)
61
+ true
41
62
  end
42
63
  end
43
64
  end
@@ -36,17 +36,23 @@ module InstantQuote
36
36
  end
37
37
 
38
38
  def get_link
39
- adapter.get_link(connection.external_id)
39
+ adapter.get_link(connection)
40
40
  end
41
41
 
42
42
  def get_quote
43
43
  params = translator.translate(connection)
44
44
 
45
- adapter.get_quote(params)
45
+ adapter.get_quote(params, connection)
46
46
  end
47
47
 
48
48
  def get_status
49
- adapter.get_status(connection.external_id)
49
+ adapter.get_status(connection.external_id, connection)
50
+ end
51
+
52
+ def get_preapproval
53
+ params = translator.translate(connection)
54
+
55
+ adapter.get_preapproval(params, connection)
50
56
  end
51
57
 
52
58
  def get_approval
@@ -6,6 +6,7 @@ require 'instant_quote/decision_parsers/capital_on_tap'
6
6
  module InstantQuote
7
7
  module Adapters
8
8
  class CapitalOnTap < Adapter
9
+ # rubocop:disable Layout/LineLength
9
10
  additional_fields [
10
11
  {
11
12
  name: 'date_of_birth',
@@ -13,16 +14,6 @@ module InstantQuote
13
14
  type: 'date',
14
15
  required: true
15
16
  },
16
- {
17
- name: 'business_landline',
18
- label: 'Business landline',
19
- required: true
20
- },
21
- {
22
- name: 'applicant_phone_number',
23
- label: 'Applicant mobile phone',
24
- required: true
25
- },
26
17
  {
27
18
  name: 'monthly_income',
28
19
  label: 'Applicant monthly income',
@@ -39,29 +30,36 @@ module InstantQuote
39
30
  },
40
31
  {
41
32
  name: 'turnover_percentage_after_feb_2020',
42
- label: 'When compared to before COVID-19, what is your current turnover level?',
33
+ label: 'What is your current turnover as a percentage of your turnover prior to February 2020?',
43
34
  required: true,
44
- choices: {
45
- 'Greater than before (>100%)' => 'GreaterThanHundredPercentage',
46
- 'Marginally reduced (80-100%)' => 'LessThanOrEqualToHunderdPercentage',
47
- 'Reduced (60-79%)' => 'LessThanSeventyNinePercentage',
48
- 'Halved (40-59%)' => 'LessThanFiftyNinePercentage',
49
- 'Less than half (20-39%)' => 'LessThanThirtyNinePercentage',
50
- 'Severely reduced or no turnover (<20%)' => 'LessThanTwentyPercentage'
51
- },
35
+ choices: [
36
+ 'My turnover had increased since covid',
37
+ 'My turnover is about the same as it was pre-covid (within 20%)',
38
+ 'My turnover has fallen materially as a result of covid (20%-60% reduction in turnover)',
39
+ 'My turnover has fallen significantly as a result of covid (more than a 60% reduction in turnover)'
40
+ ],
52
41
  type: 'select'
53
42
  },
54
43
  {
55
44
  name: 'preferred_monthly_repayment_option',
56
- label: 'What is your preferred monthly repayment option?',
45
+ label: 'How do you want to set up your direct debit for monthly repayment?',
57
46
  required: true,
58
47
  choices: [
59
- 'Minimum Amount Required',
60
- 'Full Balance',
61
- 'Fixed Amount'
48
+ 'Minimum Amount (10% of balance)',
49
+ 'Full Balance'
62
50
  ],
63
51
  type: 'select'
64
52
  },
53
+ {
54
+ name: 'send_cash_from_credit_facility_to_bank',
55
+ label: 'Do you require the ability to send cash from your credit facility to your bank?',
56
+ required: true,
57
+ choices: {
58
+ 'Yes' => 'True',
59
+ 'No' => 'False'
60
+ },
61
+ type: 'select'
62
+ },
65
63
  {
66
64
  name: 'applicant_consent',
67
65
  label: 'Yes, I give my consent for my data to be shared',
@@ -69,6 +67,7 @@ module InstantQuote
69
67
  type: 'checkbox'
70
68
  }
71
69
  ]
70
+ # rubocop:enable Layout/LineLength
72
71
 
73
72
  # Creates the quote with the information from instant connection
74
73
  def get_quote(params)
@@ -77,7 +76,7 @@ module InstantQuote
77
76
  # CoT responses can be 200 OK but still have an error!
78
77
  raise_error(response) unless response.success? && !response.error
79
78
 
80
- response.body.dig(:result)
79
+ response.body[:result]
81
80
  end
82
81
 
83
82
  # Get the status for a given application ID
@@ -104,15 +103,10 @@ module InstantQuote
104
103
  end
105
104
 
106
105
  # The link is always the same for Capital On Tap
107
- def get_link(_application_id)
106
+ def get_link(_connection)
108
107
  'https://account.capitalontap.com/apps/portal/login/'
109
108
  end
110
109
 
111
- # Capital On Tap doesn't need an approval request
112
- def get_approval(_application_id)
113
- true
114
- end
115
-
116
110
  private
117
111
 
118
112
  def raise_error(response)
@@ -44,11 +44,6 @@ module InstantQuote
44
44
  label: 'Country',
45
45
  type: 'country'
46
46
  },
47
- {
48
- name: 'applicant_phone_number',
49
- label: 'Applicant mobile number',
50
- required: true
51
- },
52
47
  {
53
48
  name: 'applicant_consent',
54
49
  label: "I agree to iwoca running soft credit checks on my personal information with \
@@ -81,7 +76,9 @@ module InstantQuote
81
76
  end
82
77
 
83
78
  # Gets the URL for the given state key.
84
- def get_link(state_key)
79
+ def get_link(connection)
80
+ state_key = connection.external_id
81
+
85
82
  response = ::Iwoca::Quote.login_link(state_key)
86
83
 
87
84
  return response.data[:login_link] if response.success?
@@ -7,11 +7,6 @@ module InstantQuote
7
7
  module Adapters
8
8
  class Optimum < Adapter
9
9
  additional_fields [
10
- {
11
- name: 'applicant_phone_number',
12
- label: 'Applicant mobile phone',
13
- required: true
14
- },
15
10
  {
16
11
  name: 'expected_turnover_next_12_months',
17
12
  label: 'Expected turnover next 12 months',
@@ -118,14 +113,10 @@ module InstantQuote
118
113
  end
119
114
 
120
115
  # Gets the URL for the given state key.
121
- def get_link(_)
116
+ def get_link(_connection)
122
117
  ''
123
118
  end
124
119
 
125
- def get_approval(_)
126
- true
127
- end
128
-
129
120
  private
130
121
 
131
122
  def decision_parser
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'youlend'
4
+ require 'instant_quote/decision_parsers/youlend'
5
+
6
+ module InstantQuote
7
+ module Adapters
8
+ class Youlend < Adapter
9
+ additional_fields [
10
+ {
11
+ name: 'monthly_card_revenue',
12
+ label: 'Avg. monthly revenue from card payments',
13
+ required: true,
14
+ type: 'money'
15
+ },
16
+ {
17
+ name: 'monthly_revenue_from_invoices',
18
+ label: 'Avg. monthly revenue from invoices',
19
+ required: true,
20
+ type: 'money'
21
+ },
22
+ {
23
+ name: 'applicant_consent',
24
+ label: 'Yes, I give my consent for my data to be shared',
25
+ required: true,
26
+ type: 'checkbox'
27
+ }
28
+ ]
29
+
30
+ # For Youlend we first need to do the pre_qualification and then, if we get a positive
31
+ # response we can create the lead. We need to call both endpoints here, so it might take a
32
+ # while.
33
+ def get_quote(params, connection)
34
+ response = ::Youlend::Lead.create(params)
35
+
36
+ if response.success?
37
+ connection.update(link: response.data[:signUpURL])
38
+
39
+ return response.data[:leadId]
40
+ end
41
+
42
+ raise_error(response)
43
+ end
44
+
45
+ def get_status(_lead_id, connection)
46
+ DecisionParsers::Youlend.new(connection.approval_decision_info)
47
+ end
48
+
49
+ # Gets the URL for the given state key.
50
+ def get_link(connection)
51
+ connection.link
52
+ end
53
+
54
+ # Checks if the application is eligible for a loan. If it is we need to update the
55
+ # connection's approval_decision_info right away, since it's the only place where we get it.
56
+ def get_preapproval(params, connection)
57
+ # The preapproval endpoint doesn't work with all params, we need to remove some
58
+ params.delete(:companyName)
59
+ params.delete(:monthsTrading)
60
+ params.delete(:keyContactName)
61
+ params.delete(:registeredAddress)
62
+ params.delete(:thirdPartyLeadId)
63
+ params.delete(:contactPhoneNumber)
64
+
65
+ response = ::Youlend::Prequalification.verify(params)
66
+
67
+ connection.update(approval_decision_info: response.data) if response.success?
68
+
69
+ response
70
+ end
71
+
72
+ private
73
+
74
+ def raise_error(response)
75
+ raise ApiError.new(
76
+ adapter: 'youlend',
77
+ data: response.body,
78
+ error: response.error || '[Youlend] API error'
79
+ )
80
+ end
81
+ end
82
+ end
83
+ end
@@ -8,6 +8,8 @@ module InstantQuote
8
8
  alias to_s error
9
9
 
10
10
  def initialize(params = {})
11
+ super
12
+
11
13
  @adapter = params[:adapter]
12
14
  @error = params[:error]
13
15
  @data = params[:data] || {}
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+
3
5
  module InstantQuote
6
+ # Inherit from this class to create the translation from Finpoint's app to the JSON that needs to
7
+ # be sent to the service you're integrating. You'll have access to `application` and `extra_info`
8
+ # from the application's record.
4
9
  class ConnectionTranslator
5
10
  attr_accessor :application, :extra_info
6
11
 
@@ -10,7 +15,7 @@ module InstantQuote
10
15
 
11
16
  def initialize(connection)
12
17
  @application = connection.finance_application
13
- @extra_info = connection.extra_info
18
+ @extra_info = ActiveSupport::HashWithIndifferentAccess.new(connection.extra_info)
14
19
  end
15
20
 
16
21
  def translate
@@ -6,60 +6,6 @@ module InstantQuote
6
6
  module ConnectionTranslators
7
7
  class CapitalOnTap < ConnectionTranslator
8
8
  DEFAULT_SALUTATION = 'Mr'
9
- LOAN_PURPOSE_MAPPING = {
10
- 'Apply for COVID-19 support/for other reasons' => 'General working capital requirements',
11
- 'Apply for COVID-19 support/to pay existing loans' => 'Repay Finances with another lender',
12
- 'Apply for COVID-19 support/to pay suppliers' => 'General working capital requirements',
13
- 'Apply for COVID-19 support/to protect jobs' => 'Payment of wages or rent',
14
- 'Apply for COVID-19 support/to refinance existing loans' => 'Repay Finances with another lender',
15
- 'Buy or develop property/buy the property my business already occupies' => '',
16
- 'Buy or develop property/buying a business that includes premises' => 'Acquisition of another business in the UK',
17
- 'Buy or develop property/buying a property for my business to move into' => '',
18
- 'Buy or develop property/develop residential or commercial premises' => 'Bridging loan',
19
- 'Buy or develop property/invest in a foreign property to rent it out' => '',
20
- 'Buy or develop property/invest in a holiday let' => '',
21
- 'Buy or develop property/invest in UK property' => 'Bridging loan',
22
- 'Buy or develop property/other property finance needs' => 'Bridging loan',
23
- 'Buy or refinance vehicle(s)/agricultural vehicle(s)' => 'General working capital requirements',
24
- 'Buy or refinance vehicle(s)/car(s)' => 'General working capital requirements',
25
- 'Buy or refinance vehicle(s)/caravan(s) & mobile home(s)' => 'General working capital requirements',
26
- 'Buy or refinance vehicle(s)/commercial vehicle(s)' => 'General working capital requirements',
27
- 'Buy or refinance vehicle(s)/fork lift truck(s)' => 'General working capital requirements',
28
- 'Buy or refinance vehicle(s)/other vehicle finance requirements' => 'General working capital requirements',
29
- 'Help with grants, tax credits and pension finance/for a research & development project' => 'Research and development activities',
30
- 'Help with grants, tax credits and pension finance/for green energy projects' => 'General working capital requirements',
31
- 'Help with grants, tax credits and pension finance/for projects with social impact' => 'General working capital requirements',
32
- 'Help with grants, tax credits and pension finance/other grant funding needs' => '',
33
- 'Help with grants, tax credits and pension finance/starting a business, incl. accelerator and incubator programs' => 'Start up costs',
34
- 'Help with grants, tax credits and pension finance/to fund skills and training initiatives' => 'General working capital requirements',
35
- 'Help with grants, tax credits and pension finance/utilise pensions to lend to a business' => '',
36
- 'Improve cashflow/borrow against monthly income from a credit card terminal' => '',
37
- 'Improve cashflow/finance overseas trading and exporting' => 'General working capital requirements',
38
- 'Improve cashflow/other cashflow requirements' => 'General working capital requirements',
39
- 'Improve cashflow/raise credit against agreed purchase orders' => 'General working capital requirements',
40
- 'Improve cashflow/release capital from pension fund(s)' => '',
41
- 'Improve cashflow/release cash from one unpaid invoice to another business' => 'General working capital requirements',
42
- 'Improve cashflow/release cash from several invoices to other businesses' => 'General working capital requirements',
43
- 'Improve cashflow/spread the cost of a large bill' => 'General working capital requirements',
44
- 'Invest in equipment or machinery/computers (hardware, software)' => 'Purchase of equipment/machinery/stock',
45
- 'Invest in equipment or machinery/equipment (office, printing, medical, etc.)' => 'Purchase of equipment/machinery/stock',
46
- 'Invest in equipment or machinery/furniture & furnishings' => 'Purchase of equipment/machinery/stock',
47
- 'Invest in equipment or machinery/machinery & tools' => 'Purchase of equipment/machinery/stock',
48
- 'Invest in equipment or machinery/other investment needs' => 'Purchase of licences,quotas or other entitlements to trade',
49
- 'Invest in equipment or machinery/phone & telecom systems' => 'Purchase of equipment/machinery/stock',
50
- 'Refinance an existing.../asset' => 'Repay Finances with another lender',
51
- 'Refinance an existing.../business loan' => 'Repay Finances with another lender',
52
- 'Refinance an existing.../commercial mortgage' => '',
53
- 'Refinance an existing.../other refinancing needs' => 'Repay Finances with another lender',
54
- 'Seeking investment/for a management buy-out' => 'Acquisition of another business in the UK',
55
- 'Seeking investment/other funding requirements' => 'General working capital requirements',
56
- 'Seeking investment/to launch a new B2B product or service' => 'Start up costs',
57
- 'Seeking investment/to launch a new consumer product or service' => 'Start up costs',
58
- 'Seeking investment/to purchase another business' => 'Acquisition of another business in the UK',
59
- 'Seeking investment/to reach more consumers with a proven product or service' => 'Expansion Activities in the UK',
60
- 'Seeking investment/to win more business clients with a proven product or service' => 'Expansion Activities in the UK',
61
- 'Seeking investment/venture builder, accelerator and incubator programs' => ''
62
- }.freeze
63
9
 
64
10
  # rubocop:disable Metrics/AbcSize
65
11
  def translate
@@ -73,7 +19,7 @@ module InstantQuote
73
19
  PersonalAddress: translate_address,
74
20
  TradingName: app_org.name,
75
21
  BusinessLegalName: app_org.name,
76
- BusinessLandline: format_phone(extra_info['business_landline']),
22
+ BusinessLandline: format_phone(extra_info['applicant_phone_number']),
77
23
  YearsTrading: app_org.years_in_business,
78
24
  MonthlyTurnOver: translate_turnover,
79
25
  BusinessType: translate_business_type,
@@ -151,20 +97,12 @@ module InstantQuote
151
97
 
152
98
  def additional_questions
153
99
  [
154
- loan_purpose_question,
155
100
  preferred_monthly_repayment_option_question,
156
- turnover_percentage_question
101
+ turnover_percentage_question,
102
+ send_cash_from_credit_facility_to_bank_question
157
103
  ]
158
104
  end
159
105
 
160
- def loan_purpose_question
161
- {
162
- question: 'What is the purpose of the loan?',
163
- answer: translate_loan_purpose,
164
- questionType: '16'
165
- }
166
- end
167
-
168
106
  def preferred_monthly_repayment_option_question
169
107
  question_from_extra_info('preferred_monthly_repayment_option', '17')
170
108
  end
@@ -173,21 +111,20 @@ module InstantQuote
173
111
  question_from_extra_info('turnover_percentage_after_feb_2020', '20')
174
112
  end
175
113
 
114
+ def send_cash_from_credit_facility_to_bank_question
115
+ question_from_extra_info('send_cash_from_credit_facility_to_bank', '23')
116
+ end
117
+
176
118
  def question_from_extra_info(name, question_type)
177
119
  field = Adapters::CapitalOnTap.additional_fields.find do |f|
178
- f[:name] == name
120
+ f[:name].to_sym == name.to_sym
179
121
  end
180
122
 
181
- { question: field[:label], answer: extra_info[field[:name]], questionType: question_type }
182
- end
183
-
184
- def translate_loan_purpose
185
- proceeds_purpose = [
186
- application.proceeds_purpose&.overview&.name,
187
- application.proceeds_purpose&.name
188
- ].join('/')
189
-
190
- LOAN_PURPOSE_MAPPING[proceeds_purpose]
123
+ {
124
+ question: field[:label],
125
+ answer: extra_info[field[:name]],
126
+ questionType: question_type
127
+ }
191
128
  end
192
129
  end
193
130
  end
@@ -78,7 +78,7 @@ module InstantQuote
78
78
  application.borrower_organisation
79
79
  end
80
80
 
81
- # rubocop:disable Metrics/AbcSize
81
+ # rubocop:disable Naming/VariableNumber
82
82
  def company_address
83
83
  {
84
84
  postcode: company.address.postcode,
@@ -88,7 +88,7 @@ module InstantQuote
88
88
  country: company.address.country
89
89
  }
90
90
  end
91
- # rubocop:enable Metrics/AbcSize
91
+ # rubocop:enable Naming/VariableNumber
92
92
 
93
93
  def person_information
94
94
  {
@@ -123,6 +123,7 @@ module InstantQuote
123
123
  }
124
124
  end
125
125
 
126
+ # rubocop:disable Naming/VariableNumber
126
127
  def person_residential_address
127
128
  {
128
129
  uid: SecureRandom.uuid,
@@ -135,6 +136,7 @@ module InstantQuote
135
136
  residential_status: home_owning_translated
136
137
  }
137
138
  end
139
+ # rubocop:enable Naming/VariableNumber
138
140
 
139
141
  def home_owning_translated
140
142
  case company.directors_home_owning.name
@@ -3,6 +3,7 @@
3
3
  module InstantQuote
4
4
  module ConnectionTranslators
5
5
  class Optimum < ConnectionTranslator
6
+ # rubocop:disable Metrics/AbcSize
6
7
  def translate
7
8
  {
8
9
  companyNumber: company&.company_number.to_s,
@@ -19,6 +20,7 @@ module InstantQuote
19
20
  quotationOnly: false
20
21
  }
21
22
  end
23
+ # rubocop:enable Metrics/AbcSize
22
24
 
23
25
  private
24
26
 
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstantQuote
4
+ module ConnectionTranslators
5
+ CURRENCY = 'GBP'
6
+
7
+ class Youlend < ConnectionTranslator
8
+ # rubocop:disable Metrics/AbcSize
9
+ def translate
10
+ {
11
+ companyName: company.name,
12
+ companyType: company_type_translated,
13
+ monthsTrading: company.total_months_in_business,
14
+ keyContactName: primary_user_name,
15
+ thirdPartyLeadId: application.code,
16
+ financialData: financial_data,
17
+ countryISOCode: 'GBR',
18
+ loanCurrencyISOCode: CURRENCY,
19
+ thirdPartyMerchantId: company.id,
20
+ thirdPartyCustomerId: application&.primary_user&.id,
21
+ registeredAddress: company_address,
22
+ contactPhoneNumber: extra_info[:applicant_phone_number],
23
+ monthlyCardRevenue: extra_info[:monthly_card_revenue].to_i,
24
+ contactEmailAddress: application&.primary_user&.email # optional
25
+ }
26
+ end
27
+ # rubocop:enable Metrics/AbcSize
28
+
29
+ private
30
+
31
+ def financial_data
32
+ {
33
+ monthlyCardRevenue: extra_info[:monthly_card_revenue].to_i,
34
+ monthlyRevenueFromInvoices: extra_info[:monthly_revenue_from_invoices].to_i,
35
+ paymentData: payment_data
36
+ }
37
+ end
38
+
39
+ def payment_data
40
+ (1..12).to_a.map do |month|
41
+ formatted_month = format('%02<month>d', month: month)
42
+
43
+ {
44
+ paymentDate: "#{Date.today.year - 1}-#{formatted_month}-01",
45
+ amount: total_amount,
46
+ currencyISOCode: CURRENCY
47
+ }
48
+ end
49
+ end
50
+
51
+ def total_amount
52
+ @total_amount ||= begin
53
+ card = extra_info[:monthly_card_revenue].to_i || 0
54
+ invoices = extra_info[:monthly_revenue_from_invoices].to_i || 0
55
+
56
+ card + invoices
57
+ end
58
+ end
59
+
60
+ def company_address
61
+ address = company.address
62
+
63
+ {
64
+ line1: address.line_1,
65
+ line2: address.line_2,
66
+ city: address.town,
67
+ region: address.town,
68
+ areaCode: address.postcode,
69
+ country: address.country
70
+ }
71
+ end
72
+
73
+ def company
74
+ @company ||= application.borrower_organisation
75
+ end
76
+
77
+ def primary_user_name
78
+ application.primary_user.name
79
+ end
80
+
81
+ def company_type_translated
82
+ case company.company_type.name
83
+ when /LTD/
84
+ 'ltd'
85
+ when /LLP/
86
+ 'llp'
87
+ when /PLC/
88
+ 'plc'
89
+ when 'Sole Trader'
90
+ 'soleTrader'
91
+ else
92
+ 'other'
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -42,7 +42,7 @@ module InstantQuote
42
42
  end
43
43
 
44
44
  def status
45
- credit_decision.dig(:status) || STATUSES[:could_not_submit]
45
+ credit_decision[:status] || STATUSES[:could_not_submit]
46
46
  end
47
47
 
48
48
  # The applicationStage can be one of the following:
@@ -52,13 +52,13 @@ module InstantQuote
52
52
  # ApprovedCredit, ApprovedPrepaid, DdSetup, AddOnSelection, DoneHavFailed,
53
53
  # DoneIdVerificationRequired, Done, Portal
54
54
  def stage
55
- data.dig(:applicationStage) || {}
55
+ data[:applicationStage] || {}
56
56
  end
57
57
 
58
58
  private
59
59
 
60
60
  def credit_decision
61
- data.dig(:creditDecision) || {}
61
+ data[:creditDecision] || {}
62
62
  end
63
63
  end
64
64
  end
@@ -91,21 +91,21 @@ module InstantQuote
91
91
 
92
92
  return 0 unless rates&.any?
93
93
 
94
- rate_info = rates.first.dig(:rates)&.first
94
+ rate_info = rates.first[:rates]&.first
95
95
 
96
96
  return 0 unless rate_info
97
97
 
98
- rate_info.dig(:rate)
98
+ rate_info[:rate]
99
99
  end
100
100
 
101
101
  def status
102
- status_hash.dig(:status) || STATUSES[:not_defined]
102
+ status_hash[:status] || STATUSES[:not_defined]
103
103
  end
104
104
 
105
105
  private
106
106
 
107
107
  def status_hash
108
- data.dig(:approval_status) || data.dig(:latest_approval_request) || {}
108
+ data[:approval_status] || data[:latest_approval_request] || {}
109
109
  end
110
110
  end
111
111
  end
@@ -6,26 +6,29 @@ module InstantQuote
6
6
  #
7
7
  # {
8
8
  # decision: {
9
- # decision: "approved",
10
- # trialPeriodMonths: 4, # trial period length
11
- # fundingLimit: 745000,
12
- # annualRenewalFee: 0,
13
- # badDebtProtection: 0.85,
14
- # cashAvailableWithinHours: 48,
15
- # discountFee: 3.35,
16
- # facility: "Factoring", # Factoring or Invoice Discounting or Confidential Invoice Discounting
17
- # prepayment: 80,
18
- # serviceFee: 1.14
9
+ # decision: "approved",
10
+ # trialPeriodMonths: 4, # trial period length
11
+ # fundingLimit: 745000,
12
+ # annualRenewalFee: 0,
13
+ # badDebtProtection: 0.85,
14
+ # cashAvailableWithinHours: 48,
15
+ # discountFee: 3.35,
16
+ # facility: "Factoring", # Factoring / Invoice Discounting / Confidential Invoice Discounting
17
+ # prepayment: 80,
18
+ # serviceFee: 1.14
19
19
  # },
20
- # opportunityId: "01234567ABCDEFGH", # the Optimum Finance opportunity ID (only supplied for successful applications that are not 'quotation only')
21
- # companyName: "COMPANY NAME LTD" # company name from the given company number - use this to verify correct company
20
+ # opportunityId: "01234567ABCDEFGH", # the Optimum Finance opportunity ID (only supplied for
21
+ # successful applications that are not 'quotation only')
22
+ #
23
+ # companyName: "COMPANY NAME LTD" # company name from the given company number - use this to
24
+ # verify correct company
22
25
  # }
23
26
 
24
27
  class Optimum < DecisionParser
25
28
  STATUSES = {
26
29
  approved: 'approved',
27
30
  declined: 'declined',
28
- referred: 'referred',
31
+ referred: 'referred'
29
32
  }.freeze
30
33
 
31
34
  LOAN_STATES = {
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstantQuote
4
+ module DecisionParsers
5
+ # Example response:
6
+ #
7
+ # {
8
+ # thirdPartyMerchantId: "b97b0834-74e5-4da6-a3df-c8dbe017fe09",
9
+ # mid: nil,
10
+ # companyName: "Test Company",
11
+ # overallCreditRiskScore: 3.5,
12
+ # overrideCreditRiskScore: 1.0,
13
+ # loanOptions: [
14
+ # { fundedAmount: 0.0, fee: 0.0, loanAmount: 0.0, sweep: 0.0, currencyISOCode: "GBP" },
15
+ # { fundedAmount: 0.0, fee: 0.0, loanAmount: 0.0, sweep: 0.0, currencyISOCode: "GBP" },
16
+ # { fundedAmount: 0.0, fee: 0.0, loanAmount: 0.0, sweep: 0.0, currencyISOCode: "GBP" }
17
+ # ]
18
+ # }
19
+ class Youlend < DecisionParser
20
+ def approved?
21
+ status_hash[:loanOptions].any?
22
+ end
23
+
24
+ def declined?
25
+ status_hash[:loanOptions].empty?
26
+ end
27
+
28
+ def sweep
29
+ first_option[:fee]
30
+ end
31
+
32
+ def fee
33
+ fee = first_option[:fee].to_f
34
+
35
+ Money.new(fee * 100).format
36
+ end
37
+
38
+ def loan_amount
39
+ amount = first_option[:loanAmount].to_f
40
+
41
+ Money.new(amount * 100).format
42
+ end
43
+
44
+ def funded_amount
45
+ amount = first_option[:fundedAmount].to_f
46
+
47
+ Money.new(amount * 100).format
48
+ end
49
+
50
+ private
51
+
52
+ def first_option
53
+ @first_option ||= status_hash[:loanOptions].find { |opt| opt[:fundedAmount].positive? }
54
+ end
55
+
56
+ def status_hash
57
+ data.presence || { loanOptions: [] }
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InstantQuote
4
- VERSION = '1.4.0'
4
+ VERSION = '1.6.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instant_quote
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - rikas
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-21 00:00:00.000000000 Z
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: simplecov
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +193,7 @@ dependencies:
165
193
  - !ruby/object:Gem::Version
166
194
  version: '0'
167
195
  - !ruby/object:Gem::Dependency
168
- name: optimum
196
+ name: money
169
197
  requirement: !ruby/object:Gem::Requirement
170
198
  requirements:
171
199
  - - ">="
@@ -179,7 +207,7 @@ dependencies:
179
207
  - !ruby/object:Gem::Version
180
208
  version: '0'
181
209
  - !ruby/object:Gem::Dependency
182
- name: money
210
+ name: optimum
183
211
  requirement: !ruby/object:Gem::Requirement
184
212
  requirements:
185
213
  - - ">="
@@ -206,6 +234,20 @@ dependencies:
206
234
  - - ">="
207
235
  - !ruby/object:Gem::Version
208
236
  version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: youlend
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
209
251
  description: Instant quote providers gem.
210
252
  email:
211
253
  - oterosantos@gmail.com
@@ -232,24 +274,27 @@ files:
232
274
  - lib/instant_quote/adapters/iwoca.rb
233
275
  - lib/instant_quote/adapters/iwoca_cbils.rb
234
276
  - lib/instant_quote/adapters/optimum.rb
277
+ - lib/instant_quote/adapters/youlend.rb
235
278
  - lib/instant_quote/api_error.rb
236
279
  - lib/instant_quote/connection_translator.rb
237
280
  - lib/instant_quote/connection_translators/capital_on_tap.rb
238
281
  - lib/instant_quote/connection_translators/iwoca.rb
239
282
  - lib/instant_quote/connection_translators/iwoca_cbils.rb
240
283
  - lib/instant_quote/connection_translators/optimum.rb
284
+ - lib/instant_quote/connection_translators/youlend.rb
241
285
  - lib/instant_quote/decision_parser.rb
242
286
  - lib/instant_quote/decision_parsers/capital_on_tap.rb
243
287
  - lib/instant_quote/decision_parsers/iwoca.rb
244
288
  - lib/instant_quote/decision_parsers/iwoca_cbils.rb
245
289
  - lib/instant_quote/decision_parsers/optimum.rb
290
+ - lib/instant_quote/decision_parsers/youlend.rb
246
291
  - lib/instant_quote/version.rb
247
292
  - lib/instant_quote/webhooks/iwoca.rb
248
293
  homepage: https://finpoint.co.uk
249
294
  licenses: []
250
295
  metadata:
251
296
  homepage_uri: https://finpoint.co.uk
252
- post_install_message:
297
+ post_install_message:
253
298
  rdoc_options: []
254
299
  require_paths:
255
300
  - lib
@@ -257,7 +302,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
257
302
  requirements:
258
303
  - - ">="
259
304
  - !ruby/object:Gem::Version
260
- version: '0'
305
+ version: 2.5.0
261
306
  required_rubygems_version: !ruby/object:Gem::Requirement
262
307
  requirements:
263
308
  - - ">="
@@ -265,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
310
  version: '0'
266
311
  requirements: []
267
312
  rubygems_version: 3.0.3
268
- signing_key:
313
+ signing_key:
269
314
  specification_version: 4
270
315
  summary: Instant quote providers gem.
271
316
  test_files: []