instant_quote 1.7.1 → 1.7.6
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 +4 -4
- data/Gemfile.lock +10 -10
- data/lib/instant_quote/adapter.rb +5 -5
- data/lib/instant_quote/adapter_finder.rb +1 -1
- data/lib/instant_quote/adapters/fake.rb +162 -0
- data/lib/instant_quote/connection_translators/fake.rb +28 -0
- data/lib/instant_quote/decision_parsers/fake.rb +82 -0
- data/lib/instant_quote/decision_parsers/youlend.rb +21 -9
- data/lib/instant_quote/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96beb49cded7a5171760d6a292781211fbf61b250d7f1d5b272a0d253386bfb9
|
4
|
+
data.tar.gz: 6a7898c6f6935549623135f789bce38c80f3ffbc5e81c35ab1a86f2c5c8e0d7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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.
|
57
|
-
money (6.14.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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(
|
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
|
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
|
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
|
@@ -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
|
-
|
25
|
+
!approved?
|
26
26
|
end
|
27
27
|
|
28
28
|
def sweep
|
29
|
-
|
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 =
|
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 =
|
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 =
|
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
|
53
|
-
@
|
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
|
-
|
65
|
+
default = { loanOptions: [] }
|
66
|
+
|
67
|
+
return default unless data && !data.empty?
|
68
|
+
|
69
|
+
data
|
58
70
|
end
|
59
71
|
end
|
60
72
|
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.
|
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-
|
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.
|
315
|
+
rubygems_version: 3.2.11
|
313
316
|
signing_key:
|
314
317
|
specification_version: 4
|
315
318
|
summary: Instant quote providers gem.
|