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 +4 -4
- data/.rubocop.yml +14 -0
- data/.travis.yml +3 -0
- data/Gemfile.lock +74 -53
- data/bin/console +6 -0
- data/instant_quote.gemspec +5 -1
- data/lib/instant_quote.rb +2 -0
- data/lib/instant_quote/adapter.rb +36 -15
- data/lib/instant_quote/adapter_finder.rb +9 -3
- data/lib/instant_quote/adapters/capital_on_tap.rb +24 -30
- data/lib/instant_quote/adapters/iwoca.rb +3 -6
- data/lib/instant_quote/adapters/optimum.rb +1 -10
- data/lib/instant_quote/adapters/youlend.rb +83 -0
- data/lib/instant_quote/api_error.rb +2 -0
- data/lib/instant_quote/connection_translator.rb +6 -1
- data/lib/instant_quote/connection_translators/capital_on_tap.rb +13 -76
- data/lib/instant_quote/connection_translators/iwoca.rb +4 -2
- data/lib/instant_quote/connection_translators/optimum.rb +2 -0
- data/lib/instant_quote/connection_translators/youlend.rb +97 -0
- data/lib/instant_quote/decision_parsers/capital_on_tap.rb +3 -3
- data/lib/instant_quote/decision_parsers/iwoca.rb +4 -4
- data/lib/instant_quote/decision_parsers/optimum.rb +16 -13
- data/lib/instant_quote/decision_parsers/youlend.rb +61 -0
- data/lib/instant_quote/version.rb +1 -1
- metadata +53 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8a949bc8d63fd2ad95636f7a72ff7e8a9f801927eea13634681a20321abf0e5
|
|
4
|
+
data.tar.gz: 25822b27eabbe49c12a40dfd97b614c6d80d17c69ee83f48e0f20149264d4be8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
data/Gemfile.lock
CHANGED
|
@@ -1,46 +1,50 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
instant_quote (1.
|
|
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.
|
|
16
|
+
activesupport (6.1.1)
|
|
16
17
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
17
|
-
i18n (>=
|
|
18
|
-
minitest (
|
|
19
|
-
tzinfo (~>
|
|
20
|
-
zeitwerk (~> 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.
|
|
24
|
-
byebug (11.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.
|
|
32
|
-
concurrent-ruby (1.1.
|
|
33
|
-
crack (0.4.
|
|
34
|
-
|
|
35
|
-
diff-lcs (1.
|
|
36
|
-
docile (1.3.
|
|
37
|
-
dotenv (2.7.
|
|
38
|
-
faraday (1.0
|
|
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.
|
|
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.
|
|
54
|
-
money (6.
|
|
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.
|
|
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.
|
|
65
|
-
parser (
|
|
66
|
-
ast (~> 2.4.
|
|
67
|
-
phonelib (0.6.
|
|
68
|
-
pry (0.13.
|
|
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.
|
|
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.
|
|
79
|
-
rspec-core (~> 3.
|
|
80
|
-
rspec-expectations (~> 3.
|
|
81
|
-
rspec-mocks (~> 3.
|
|
82
|
-
rspec-core (3.
|
|
83
|
-
rspec-support (~> 3.
|
|
84
|
-
rspec-expectations (3.
|
|
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.
|
|
87
|
-
rspec-mocks (3.
|
|
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.
|
|
90
|
-
rspec-support (3.
|
|
91
|
-
rubocop (
|
|
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 (>=
|
|
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, <
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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.
|
|
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'
|
data/instant_quote.gemspec
CHANGED
|
@@ -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 ||
|
|
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
|
-
|
|
22
|
+
def self.get_link(connection)
|
|
23
|
+
new.get_link(connection)
|
|
9
24
|
end
|
|
10
25
|
|
|
11
|
-
def self.
|
|
12
|
-
new.
|
|
26
|
+
def self.get_quote(params, connection = nil)
|
|
27
|
+
new.get_quote(params, connection)
|
|
13
28
|
end
|
|
14
29
|
|
|
15
|
-
def self.
|
|
16
|
-
new.
|
|
30
|
+
def self.get_status(application_id, connection = nil)
|
|
31
|
+
new.get_status(application_id, connection)
|
|
17
32
|
end
|
|
18
33
|
|
|
19
|
-
def self.
|
|
20
|
-
new.
|
|
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
|
-
|
|
40
|
-
|
|
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
|
|
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: '
|
|
33
|
+
label: 'What is your current turnover as a percentage of your turnover prior to February 2020?',
|
|
43
34
|
required: true,
|
|
44
|
-
choices:
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
|
|
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: '
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
@@ -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['
|
|
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
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
55
|
+
data[:applicationStage] || {}
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
private
|
|
59
59
|
|
|
60
60
|
def credit_decision
|
|
61
|
-
data
|
|
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
|
|
94
|
+
rate_info = rates.first[:rates]&.first
|
|
95
95
|
|
|
96
96
|
return 0 unless rate_info
|
|
97
97
|
|
|
98
|
-
rate_info
|
|
98
|
+
rate_info[:rate]
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def status
|
|
102
|
-
status_hash
|
|
102
|
+
status_hash[:status] || STATUSES[:not_defined]
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
private
|
|
106
106
|
|
|
107
107
|
def status_hash
|
|
108
|
-
data
|
|
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
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
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
|
|
21
|
-
#
|
|
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
|
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
|
+
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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: []
|