instant_quote 1.7.4 → 1.7.9

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: 15d07ba008846c863937a179a6d330833031b4291a595f30bf0701980a3c1bc0
4
- data.tar.gz: 102ede083d49fc37c21ab29277e8eed0433fe4961dca1bffb9576c641b002894
3
+ metadata.gz: 020136bd81726c4c518ce0bc6aa07bfb91b8b8e9f0303dce318122e07935ff22
4
+ data.tar.gz: c75a46be6ec8041c6d906ba668ef85eb582fea9f4ac0da5c849a817588d97061
5
5
  SHA512:
6
- metadata.gz: 00b3e2c8bb67d19a2e2be46bd261404bf0763a2876d1a32fbdd1bcbe8f584759485c3566d7c049a511958ae0a02c8cd4c7a6987647d822e1715e62196b8af315
7
- data.tar.gz: 4c85a4d8f1d65aae349b62c2defb1d01e5342444ed2a345da25b3f7e27d0e77a37a08d947e9c2a743f4d80e9c511c2e77797385bad1bb2442cb8c8a08ccc71ea
6
+ metadata.gz: 786214591b9250b2cda9fc3a455d1f0e965abc40186e393ca1e20099724ebd3402ff5696065b2a744197c44909947a4f792f2732a7ddada9419648b1db3b7641
7
+ data.tar.gz: 8cebf1be41fa00a3d7b9d25e0cb772ea072fb9a19e0c228b133da971992ba1bd216263bb6b33729ce220427486e5a99fb4b0b4d21791d9620d01bce42dcfabe5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- instant_quote (1.7.4)
4
+ instant_quote (1.7.9)
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.3)
16
+ activesupport (6.1.3.1)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
@@ -36,15 +36,19 @@ GEM
36
36
  diff-lcs (1.4.4)
37
37
  docile (1.3.5)
38
38
  dotenv (2.7.6)
39
- faraday (1.3.0)
39
+ faraday (1.4.1)
40
+ faraday-excon (~> 1.1)
40
41
  faraday-net_http (~> 1.0)
42
+ faraday-net_http_persistent (~> 1.1)
41
43
  multipart-post (>= 1.2, < 3)
42
- ruby2_keywords
44
+ ruby2_keywords (>= 0.0.4)
45
+ faraday-excon (1.1.0)
43
46
  faraday-net_http (1.0.1)
47
+ faraday-net_http_persistent (1.1.0)
44
48
  faraday_middleware (1.0.0)
45
49
  faraday (~> 1.0)
46
50
  hashdiff (1.0.1)
47
- i18n (1.8.9)
51
+ i18n (1.8.10)
48
52
  concurrent-ruby (~> 1.0)
49
53
  iwoca (1.0.0)
50
54
  addressable
@@ -53,8 +57,8 @@ GEM
53
57
  multi_json
54
58
  rainbow
55
59
  method_source (1.0.0)
56
- minitest (5.14.3)
57
- money (6.14.0)
60
+ minitest (5.14.4)
61
+ money (6.14.1)
58
62
  i18n (>= 0.6.4, <= 2)
59
63
  multi_json (1.15.0)
60
64
  multipart-post (2.1.1)
@@ -67,7 +71,7 @@ GEM
67
71
  parallel (1.20.1)
68
72
  parser (3.0.0.0)
69
73
  ast (~> 2.4.1)
70
- phonelib (0.6.48)
74
+ phonelib (0.6.49)
71
75
  pry (0.13.1)
72
76
  coderay (~> 1.1)
73
77
  method_source (~> 1.0)
@@ -77,7 +81,7 @@ GEM
77
81
  public_suffix (4.0.6)
78
82
  rainbow (3.0.0)
79
83
  rake (10.5.0)
80
- regexp_parser (2.0.3)
84
+ regexp_parser (2.1.1)
81
85
  rexml (3.2.4)
82
86
  rspec (3.10.0)
83
87
  rspec-core (~> 3.10.0)
@@ -92,7 +96,7 @@ GEM
92
96
  diff-lcs (>= 1.2.0, < 2.0)
93
97
  rspec-support (~> 3.10.0)
94
98
  rspec-support (3.10.2)
95
- rubocop (1.9.1)
99
+ rubocop (1.11.0)
96
100
  parallel (~> 1.10)
97
101
  parser (>= 3.0.0.0)
98
102
  rainbow (>= 2.2.2, < 4.0)
@@ -119,7 +123,7 @@ GEM
119
123
  tzinfo (2.0.4)
120
124
  concurrent-ruby (~> 1.0)
121
125
  unicode-display_width (2.0.0)
122
- webmock (3.11.2)
126
+ webmock (3.12.1)
123
127
  addressable (>= 2.3.6)
124
128
  crack (>= 0.3.2)
125
129
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -148,4 +152,4 @@ DEPENDENCIES
148
152
  webmock
149
153
 
150
154
  BUNDLED WITH
151
- 2.2.5
155
+ 2.2.11
@@ -28,18 +28,6 @@ module InstantQuote
28
28
  required: true,
29
29
  if: ->(app) { app.borrower_organisation.sole_trader? }
30
30
  },
31
- {
32
- name: 'turnover_percentage_after_feb_2020',
33
- label: 'What is your current turnover as a percentage of your turnover prior to February 2020?',
34
- required: true,
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
- ],
41
- type: 'select'
42
- },
43
31
  {
44
32
  name: 'preferred_monthly_repayment_option',
45
33
  label: 'How do you want to set up your direct debit for monthly repayment?',
@@ -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
@@ -75,7 +75,7 @@ module InstantQuote
75
75
  raise ApiError.new(
76
76
  adapter: 'youlend',
77
77
  data: response.body,
78
- error: response.error || '[Youlend] API error'
78
+ error: response.errors.first || '[Youlend] API error'
79
79
  )
80
80
  end
81
81
  end
@@ -72,9 +72,12 @@ module InstantQuote
72
72
  }
73
73
  end
74
74
 
75
+ # TODO: this is no longer true, but we are still keeping the range for legacy reasons.
75
76
  # Since in Finpoint the user selects an intervel (i.e. '500,000 - 999,999'). We get the avg
76
77
  # on this interval and use that number as the monthly turnover.
77
78
  def translate_turnover
79
+ return app_org.turnover_pennies.to_i if app_org.turnover_pennies
80
+
78
81
  turnover = app_org.turnover_range
79
82
 
80
83
  ((turnover.from + turnover.to) / 2 / 100).ceil
@@ -98,7 +101,6 @@ module InstantQuote
98
101
  def additional_questions
99
102
  [
100
103
  preferred_monthly_repayment_option_question,
101
- turnover_percentage_question,
102
104
  send_cash_from_credit_facility_to_bank_question
103
105
  ]
104
106
  end
@@ -107,10 +109,6 @@ module InstantQuote
107
109
  question_from_extra_info('preferred_monthly_repayment_option', '17')
108
110
  end
109
111
 
110
- def turnover_percentage_question
111
- question_from_extra_info('turnover_percentage_after_feb_2020', '20')
112
- end
113
-
114
112
  def send_cash_from_credit_facility_to_bank_question
115
113
  question_from_extra_info('send_cash_from_credit_facility_to_bank', '23')
116
114
  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,7 +18,9 @@ module InstantQuote
18
18
  # }
19
19
  class Youlend < DecisionParser
20
20
  def approved?
21
- status_hash[:loanOptions].any? && first_option
21
+ return false unless status_hash[:loanOptions]
22
+
23
+ status_hash[:loanOptions].any? && !funded_option.empty?
22
24
  end
23
25
 
24
26
  def declined?
@@ -26,7 +28,7 @@ module InstantQuote
26
28
  end
27
29
 
28
30
  def sweep
29
- first_option[:sweep]
31
+ funded_option[:sweep]
30
32
  end
31
33
 
32
34
  def status
@@ -34,21 +36,19 @@ module InstantQuote
34
36
  end
35
37
 
36
38
  def fee
37
- return 0.0 unless first_option
38
-
39
- fee = first_option[:fee].to_f
39
+ fee = funded_option[:fee].to_f
40
40
 
41
41
  Money.new(fee * 100).format
42
42
  end
43
43
 
44
44
  def loan_amount
45
- amount = first_option[:loanAmount].to_f
45
+ amount = funded_option[:loanAmount].to_f
46
46
 
47
47
  Money.new(amount * 100).format
48
48
  end
49
49
 
50
50
  def funded_amount
51
- amount = first_option[:fundedAmount].to_f
51
+ amount = funded_option[:fundedAmount].to_f
52
52
 
53
53
  Money.new(amount * 100).format
54
54
  end
@@ -57,8 +57,10 @@ module InstantQuote
57
57
 
58
58
  private
59
59
 
60
- def first_option
61
- @first_option ||= status_hash[:loanOptions].find { |opt| opt[:fundedAmount].positive? }
60
+ def funded_option
61
+ @funded_option ||= status_hash[:loanOptions].find(-> { {} }) do |opt|
62
+ opt[:fundedAmount].positive?
63
+ end
62
64
  end
63
65
 
64
66
  def status_hash
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InstantQuote
4
- VERSION = '1.7.4'
4
+ VERSION = '1.7.9'
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.4
4
+ version: 1.7.9
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-20 00:00:00.000000000 Z
11
+ date: 2021-04-28 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.