instant_quote 1.7.1 → 1.7.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9bf0f31162c311de2e55f0cf43374e6ffd50d801217f0dc45900db6c9b534f2
4
- data.tar.gz: 06e7891f4b7b30db6e8fdbd8318d5e454db243f6b0c9cac542ab98b2872fe203
3
+ metadata.gz: 96beb49cded7a5171760d6a292781211fbf61b250d7f1d5b272a0d253386bfb9
4
+ data.tar.gz: 6a7898c6f6935549623135f789bce38c80f3ffbc5e81c35ab1a86f2c5c8e0d7d
5
5
  SHA512:
6
- metadata.gz: ad3b07afbed20ccce134724a6c44995aa56ba7d399bacc0fdfffecc0c298e3a08163675475cc6277810dd9a517c65d42f40ccfd3e40267f2b7e4d1629387b22c
7
- data.tar.gz: 88f7f388923aae37307902617804284ac134b4611004321585312d9d09e0181cb6503661ade3b3e82509aab9090bddc5b32f82af3cc514bf37ec505b96586f0d
6
+ metadata.gz: 2a418819d1720e7601349dab5a14e23fb09631f8a23dc427a6b7ac69c5ab9aaf2741acfecfb4c96767fc309d891b9a76e8a7dc43e661ec96757437ea7e2adb43
7
+ data.tar.gz: a1d6f7680f96dffe4f403ca116a153d46169d314b2d9ac490b8b65f796594ffbc0c4976f84066f81e3c4d60023f467b8e9cdf7f490087f5983ab9da9c2f15938
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- instant_quote (1.7.1)
4
+ instant_quote (1.7.6)
5
5
  activesupport
6
6
  capital_on_tap
7
7
  iwoca
@@ -13,7 +13,7 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- activesupport (6.1.1)
16
+ activesupport (6.1.3)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
@@ -44,7 +44,7 @@ GEM
44
44
  faraday_middleware (1.0.0)
45
45
  faraday (~> 1.0)
46
46
  hashdiff (1.0.1)
47
- i18n (1.8.8)
47
+ i18n (1.8.9)
48
48
  concurrent-ruby (~> 1.0)
49
49
  iwoca (1.0.0)
50
50
  addressable
@@ -53,8 +53,8 @@ GEM
53
53
  multi_json
54
54
  rainbow
55
55
  method_source (1.0.0)
56
- minitest (5.14.3)
57
- money (6.14.0)
56
+ minitest (5.14.4)
57
+ money (6.14.1)
58
58
  i18n (>= 0.6.4, <= 2)
59
59
  multi_json (1.15.0)
60
60
  multipart-post (2.1.1)
@@ -67,7 +67,7 @@ GEM
67
67
  parallel (1.20.1)
68
68
  parser (3.0.0.0)
69
69
  ast (~> 2.4.1)
70
- phonelib (0.6.48)
70
+ phonelib (0.6.49)
71
71
  pry (0.13.1)
72
72
  coderay (~> 1.1)
73
73
  method_source (~> 1.0)
@@ -77,7 +77,7 @@ GEM
77
77
  public_suffix (4.0.6)
78
78
  rainbow (3.0.0)
79
79
  rake (10.5.0)
80
- regexp_parser (2.0.3)
80
+ regexp_parser (2.1.1)
81
81
  rexml (3.2.4)
82
82
  rspec (3.10.0)
83
83
  rspec-core (~> 3.10.0)
@@ -92,7 +92,7 @@ GEM
92
92
  diff-lcs (>= 1.2.0, < 2.0)
93
93
  rspec-support (~> 3.10.0)
94
94
  rspec-support (3.10.2)
95
- rubocop (1.9.1)
95
+ rubocop (1.11.0)
96
96
  parallel (~> 1.10)
97
97
  parser (>= 3.0.0.0)
98
98
  rainbow (>= 2.2.2, < 4.0)
@@ -119,7 +119,7 @@ GEM
119
119
  tzinfo (2.0.4)
120
120
  concurrent-ruby (~> 1.0)
121
121
  unicode-display_width (2.0.0)
122
- webmock (3.11.2)
122
+ webmock (3.12.1)
123
123
  addressable (>= 2.3.6)
124
124
  crack (>= 0.3.2)
125
125
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -148,4 +148,4 @@ DEPENDENCIES
148
148
  webmock
149
149
 
150
150
  BUNDLED WITH
151
- 2.2.5
151
+ 2.2.11
@@ -39,7 +39,7 @@ module InstantQuote
39
39
  new.get_approval(application_id, connection)
40
40
  end
41
41
 
42
- def get_link(_application_id, _connection)
42
+ def get_link(_connection)
43
43
  raise NotImplementedError, "You must implement '#{self.class.name}#get_link'"
44
44
  end
45
45
 
@@ -51,14 +51,14 @@ module InstantQuote
51
51
  raise NotImplementedError, "You must implement '#{self.class.name}#get_status'"
52
52
  end
53
53
 
54
- # Default for pre approval will be true, override it in the adapter class if needed.
54
+ # Default for pre approval will be success, override it in the adapter class if needed.
55
55
  def get_preapproval(_params, _connection)
56
- true
56
+ OpenStruct.new(success?: true)
57
57
  end
58
58
 
59
- # Default for approval will be true, override it in the adapter class if needed.
59
+ # Default for approval will be success, override it in the adapter class if needed.
60
60
  def get_approval(_application_id, _connection)
61
- true
61
+ OpenStruct.new(success?: true)
62
62
  end
63
63
  end
64
64
  end
@@ -56,7 +56,7 @@ module InstantQuote
56
56
  end
57
57
 
58
58
  def get_approval
59
- adapter.get_approval(connection.external_id)
59
+ adapter.get_approval(connection.external_id, connection)
60
60
  end
61
61
 
62
62
  def additional_fields
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'instant_quote/decision_parsers/fake'
5
+
6
+ module InstantQuote
7
+ module Adapters
8
+ class Fake < Adapter
9
+ additional_fields [
10
+ {
11
+ name: 'date_of_birth',
12
+ label: 'Date of birth',
13
+ type: 'date',
14
+ required: true
15
+ },
16
+ {
17
+ name: 'desired_status',
18
+ label: 'What status do you want to get back?',
19
+ required: true,
20
+ choices: {
21
+ 'Pending' => 'pending',
22
+ 'Approved' => 'approved',
23
+ 'Declined' => 'declined',
24
+ 'No decision possible' => 'no_decision_possible',
25
+ 'Error on get_quote' => 'error_on_get_quote',
26
+ 'Error on get_status' => 'error_on_get_status'
27
+ },
28
+ type: 'select'
29
+ },
30
+ {
31
+ name: 'decision_info_html',
32
+ label: 'What html you want to render for decision info?',
33
+ required: true,
34
+ choices: {
35
+ 'Iwoca' => 'iwoca',
36
+ 'Iwoca CBILS' => 'iwoca_cbils',
37
+ 'Capital on tap' => 'capital_on_tap',
38
+ 'Optimum' => 'optimum',
39
+ 'Youlend' => 'youlend'
40
+ },
41
+ type: 'select'
42
+ },
43
+ {
44
+ name: 'with_preapproval',
45
+ label: 'Preapproval?',
46
+ choices: {
47
+ 'No' => 'no',
48
+ 'Yes (success)' => 'yes_success',
49
+ 'Yes (decline)' => 'yes_decline'
50
+ },
51
+ type: 'select'
52
+ },
53
+ {
54
+ name: 'with_approval',
55
+ label: 'With approval?',
56
+ choices: {
57
+ 'No' => 'no',
58
+ 'Yes' => 'yes'
59
+ },
60
+ type: 'select'
61
+ },
62
+ {
63
+ name: 'applicant_consent',
64
+ label: 'Yes, I give my consent for my data to be shared',
65
+ required: true,
66
+ type: 'checkbox'
67
+ }
68
+ ]
69
+
70
+ # TODO: what should we do here?
71
+ def get_approval(_state_key, _connection)
72
+ true
73
+ end
74
+
75
+ def get_preapproval(params, _connection)
76
+ response = OpenStruct.new(success?: true, error_description: '')
77
+
78
+ return response if params[:with_preapproval] == 'no'
79
+
80
+ if params[:with_preapproval] == 'yes_decline'
81
+ response[:success?] = false
82
+ response.error_description = 'preapproval is declined'
83
+ end
84
+
85
+ response
86
+ end
87
+
88
+ def get_quote(params, _connection)
89
+ if params[:desired_status] == 'error_on_get_quote'
90
+ response = OpenStruct.new(
91
+ body: { errorMessage: 'Error on get_quote that raises an exception' },
92
+ error: '501 error_on_get_quote'
93
+ )
94
+ raise_error(response)
95
+ end
96
+
97
+ # Returns a random identifier
98
+ SecureRandom.hex(3)
99
+ end
100
+
101
+ # Get the status for a given application ID
102
+ # rubocop:disable Metrics/AbcSize
103
+ # rubocop:disable Metrics/MethodLength
104
+ def get_status(_application_id, connection)
105
+ status = connection.extra_info['desired_status']
106
+
107
+ if status == 'error_on_get_status'
108
+ response = OpenStruct.new(
109
+ body: { errorMessage: 'Error on get_status that raises an exception' },
110
+ error: '502 error_on_get_status'
111
+ )
112
+ raise_error(response) unless response.success?
113
+ end
114
+
115
+ response = OpenStruct.new(
116
+ body: {
117
+ latest_approval_request: {
118
+ status: status,
119
+ approved: {
120
+ interval: rand(10..30),
121
+ duration: rand(10..30),
122
+ max_credit: rand(1000..8000),
123
+ monthly_interest_rate: rand(0..1.0).round(2)
124
+ }
125
+ },
126
+ credit_decision: {
127
+ status: status,
128
+ sweep: 10,
129
+ loan_amount: rand(1000..8000),
130
+ funded_amount: rand(1000..8000),
131
+ fee: rand(100..800),
132
+ monthly_interest_rate: rand(0..1.0).round(2),
133
+ monthly_card_interest_rate: rand(0..1.0).round(2),
134
+ amount: rand(1000..8000)
135
+ }
136
+ }
137
+ )
138
+
139
+ DecisionParsers::Fake.new(response.body)
140
+ end
141
+ # rubocop:enable Metrics/AbcSize
142
+ # rubocop:enable Metrics/MethodLength
143
+
144
+ # The link is always the same
145
+ def get_link(connection)
146
+ id = connection.external_id
147
+
148
+ "https://fake.com/link/#{id}"
149
+ end
150
+
151
+ private
152
+
153
+ def raise_error(response)
154
+ raise ApiError.new(
155
+ adapter: 'fake',
156
+ data: response.body,
157
+ error: response.error || 'Unknown API error'
158
+ )
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstantQuote
4
+ module ConnectionTranslators
5
+ class Fake < ConnectionTranslator
6
+ def translate
7
+ {
8
+ salutation: app_user.salutation,
9
+ first_name: app_user.first_name,
10
+ last_name: app_user.last_name,
11
+ date_of_birth: extra_info['date_of_birth'],
12
+ registration_number: app_org.company_number,
13
+ desired_status: extra_info['desired_status']
14
+ }
15
+ end
16
+
17
+ private
18
+
19
+ def app_user
20
+ application.primary_user
21
+ end
22
+
23
+ def app_org
24
+ application.borrower_organisation
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'money'
4
+
5
+ module InstantQuote
6
+ module DecisionParsers
7
+ class Fake < DecisionParser
8
+ STATUSES = {
9
+ pending: 'pending',
10
+ approved: 'approved',
11
+ declined: 'declined',
12
+ could_not_submit: 'CouldNotSubmit',
13
+ no_decision: 'no_decision_possible'
14
+ }.freeze
15
+
16
+ def pending?
17
+ status == STATUSES[:pending]
18
+ end
19
+
20
+ def approved?
21
+ status == STATUSES[:approved]
22
+ end
23
+
24
+ def declined?
25
+ status == STATUSES[:declined]
26
+ end
27
+
28
+ def credit_duration
29
+ credit_decision.dig(:approved, :duration)
30
+ end
31
+
32
+ def credit_interval
33
+ credit_decision.dig(:approved, :interval)
34
+ end
35
+
36
+ def sweep
37
+ credit_decision[:sweep]
38
+ end
39
+
40
+ def fee
41
+ fee = credit_decision[:fee].to_f
42
+
43
+ Money.new(fee * 100).format
44
+ end
45
+
46
+ def amount
47
+ Money.new(credit_decision[:amount].to_f * 100).format
48
+ end
49
+
50
+ def loan_amount
51
+ amount = credit_decision[:loan_amount].to_f
52
+
53
+ Money.new(amount * 100).format
54
+ end
55
+
56
+ def funded_amount
57
+ amount = credit_decision[:funded_amount].to_f
58
+
59
+ Money.new(amount * 100).format
60
+ end
61
+
62
+ def monthly_interest_rate
63
+ credit_decision[:monthly_interes_rate] ||
64
+ credit_decision.dig(:approved, :monthly_interest_rate) || 0.0
65
+ end
66
+
67
+ def monthly_card_interest_rate
68
+ credit_decision[:monthly_card_interes_rate] || 0.0
69
+ end
70
+
71
+ def status
72
+ credit_decision[:status] || STATUSES[:could_not_submit]
73
+ end
74
+
75
+ private
76
+
77
+ def credit_decision
78
+ data[:credit_decision] || data[:latest_approval_request] || {}
79
+ end
80
+ end
81
+ end
82
+ end
@@ -18,43 +18,55 @@ module InstantQuote
18
18
  # }
19
19
  class Youlend < DecisionParser
20
20
  def approved?
21
- status_hash[:loanOptions].any?
21
+ status_hash[:loanOptions].any? && !funded_option.empty?
22
22
  end
23
23
 
24
24
  def declined?
25
- status_hash[:loanOptions].empty?
25
+ !approved?
26
26
  end
27
27
 
28
28
  def sweep
29
- first_option[:sweep]
29
+ funded_option[:sweep]
30
+ end
31
+
32
+ def status
33
+ approved? ? 'approved' : 'declined'
30
34
  end
31
35
 
32
36
  def fee
33
- fee = first_option[:fee].to_f
37
+ fee = funded_option[:fee].to_f
34
38
 
35
39
  Money.new(fee * 100).format
36
40
  end
37
41
 
38
42
  def loan_amount
39
- amount = first_option[:loanAmount].to_f
43
+ amount = funded_option[:loanAmount].to_f
40
44
 
41
45
  Money.new(amount * 100).format
42
46
  end
43
47
 
44
48
  def funded_amount
45
- amount = first_option[:fundedAmount].to_f
49
+ amount = funded_option[:fundedAmount].to_f
46
50
 
47
51
  Money.new(amount * 100).format
48
52
  end
49
53
 
54
+ alias amount funded_amount
55
+
50
56
  private
51
57
 
52
- def first_option
53
- @first_option ||= status_hash[:loanOptions].find { |opt| opt[:fundedAmount].positive? }
58
+ def funded_option
59
+ @funded_option ||= status_hash[:loanOptions].find(-> { {} }) do |opt|
60
+ opt[:fundedAmount].positive?
61
+ end
54
62
  end
55
63
 
56
64
  def status_hash
57
- data.presence || { loanOptions: [] }
65
+ default = { loanOptions: [] }
66
+
67
+ return default unless data && !data.empty?
68
+
69
+ data
58
70
  end
59
71
  end
60
72
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InstantQuote
4
- VERSION = '1.7.1'
4
+ VERSION = '1.7.6'
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.7.1
4
+ version: 1.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - rikas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-09 00:00:00.000000000 Z
11
+ date: 2021-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -271,6 +271,7 @@ files:
271
271
  - lib/instant_quote/adapter.rb
272
272
  - lib/instant_quote/adapter_finder.rb
273
273
  - lib/instant_quote/adapters/capital_on_tap.rb
274
+ - lib/instant_quote/adapters/fake.rb
274
275
  - lib/instant_quote/adapters/iwoca.rb
275
276
  - lib/instant_quote/adapters/iwoca_cbils.rb
276
277
  - lib/instant_quote/adapters/optimum.rb
@@ -278,12 +279,14 @@ files:
278
279
  - lib/instant_quote/api_error.rb
279
280
  - lib/instant_quote/connection_translator.rb
280
281
  - lib/instant_quote/connection_translators/capital_on_tap.rb
282
+ - lib/instant_quote/connection_translators/fake.rb
281
283
  - lib/instant_quote/connection_translators/iwoca.rb
282
284
  - lib/instant_quote/connection_translators/iwoca_cbils.rb
283
285
  - lib/instant_quote/connection_translators/optimum.rb
284
286
  - lib/instant_quote/connection_translators/youlend.rb
285
287
  - lib/instant_quote/decision_parser.rb
286
288
  - lib/instant_quote/decision_parsers/capital_on_tap.rb
289
+ - lib/instant_quote/decision_parsers/fake.rb
287
290
  - lib/instant_quote/decision_parsers/iwoca.rb
288
291
  - lib/instant_quote/decision_parsers/iwoca_cbils.rb
289
292
  - lib/instant_quote/decision_parsers/optimum.rb
@@ -309,7 +312,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
309
312
  - !ruby/object:Gem::Version
310
313
  version: '0'
311
314
  requirements: []
312
- rubygems_version: 3.0.3
315
+ rubygems_version: 3.2.11
313
316
  signing_key:
314
317
  specification_version: 4
315
318
  summary: Instant quote providers gem.