mas-rad_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +3 -0
  4. data/Rakefile +14 -0
  5. data/app/models/accreditation.rb +5 -0
  6. data/app/models/adviser.rb +61 -0
  7. data/app/models/allowed_payment_method.rb +7 -0
  8. data/app/models/authentication.rb +19 -0
  9. data/app/models/firm.rb +143 -0
  10. data/app/models/in_person_advice_method.rb +7 -0
  11. data/app/models/initial_advice_fee_structure.rb +7 -0
  12. data/app/models/initial_meeting_duration.rb +7 -0
  13. data/app/models/investment_size.rb +7 -0
  14. data/app/models/lookup/adviser.rb +10 -0
  15. data/app/models/lookup/firm.rb +17 -0
  16. data/app/models/lookup/subsidiary.rb +11 -0
  17. data/app/models/ongoing_advice_fee_structure.rb +7 -0
  18. data/app/models/other_advice_method.rb +7 -0
  19. data/app/models/principal.rb +94 -0
  20. data/app/models/professional_body.rb +3 -0
  21. data/app/models/professional_standing.rb +3 -0
  22. data/app/models/qualification.rb +5 -0
  23. data/app/models/travel_distance.rb +15 -0
  24. data/config/routes.rb +2 -0
  25. data/db/migrate/20141211110031_create_lookup_firms.rb +11 -0
  26. data/db/migrate/20141221140208_create_principals.rb +23 -0
  27. data/db/migrate/20141222150416_add_last_sign_in_at_to_principal.rb +5 -0
  28. data/db/migrate/20141230112136_create_lookup_subsidiaries.rb +10 -0
  29. data/db/migrate/20150106115732_remove_last_sign_in_at_from_principals.rb +5 -0
  30. data/db/migrate/20150114144343_create_lookup_advisers.rb +10 -0
  31. data/db/migrate/20150114151447_create_firms.rb +13 -0
  32. data/db/migrate/20150115130949_add_address_to_firm.rb +9 -0
  33. data/db/migrate/20150119102735_create_in_person_advice_methods.rb +15 -0
  34. data/db/migrate/20150119111754_create_other_advice_methods.rb +15 -0
  35. data/db/migrate/20150119114218_add_free_initial_meeting_to_firm.rb +5 -0
  36. data/db/migrate/20150119125208_create_initial_meeting_durations.rb +11 -0
  37. data/db/migrate/20150119152325_create_initial_advice_fee_structures.rb +15 -0
  38. data/db/migrate/20150119152336_create_ongoing_advice_fee_structures.rb +15 -0
  39. data/db/migrate/20150120133717_create_allowed_payment_methods.rb +15 -0
  40. data/db/migrate/20150120141928_add_minimum_fixed_fee_to_firm.rb +5 -0
  41. data/db/migrate/20150120150738_create_investment_sizes.rb +15 -0
  42. data/db/migrate/20150121110757_create_advisers.rb +11 -0
  43. data/db/migrate/20150121123437_add_business_income_breakdown_fields_to_firm.rb +11 -0
  44. data/db/migrate/20150121134845_create_qualifications.rb +15 -0
  45. data/db/migrate/20150121154458_create_accreditations.rb +15 -0
  46. data/db/migrate/20150121173015_create_professional_standings.rb +15 -0
  47. data/db/migrate/20150121181341_create_professional_bodies.rb +15 -0
  48. data/db/migrate/20150121183728_add_confirmed_disclaimer_to_advisers.rb +5 -0
  49. data/db/migrate/20150124124350_add_geographical_fields_to_adviser.rb +7 -0
  50. data/db/migrate/20150125145457_add_parent_id_to_firms.rb +5 -0
  51. data/db/migrate/20150125164156_remove_unique_constraint_from_firms_fca_number.rb +5 -0
  52. data/db/migrate/20150127084858_add_ordering_on_reference_data.rb +31 -0
  53. data/db/migrate/20150209144836_remove_covers_whole_of_uk_from_advisers.rb +17 -0
  54. data/lib/mas/rad_core.rb +4 -0
  55. data/lib/mas/rad_core/engine.rb +21 -0
  56. data/lib/mas/rad_core/version.rb +5 -0
  57. data/lib/mas/stats.rb +19 -0
  58. data/lib/mas/tasks/rad_core_tasks.rake +4 -0
  59. data/spec/dummy/Rakefile +6 -0
  60. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  61. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  62. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  64. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  65. data/spec/dummy/bin/bundle +3 -0
  66. data/spec/dummy/bin/rails +4 -0
  67. data/spec/dummy/bin/rake +4 -0
  68. data/spec/dummy/bin/setup +29 -0
  69. data/spec/dummy/config.ru +4 -0
  70. data/spec/dummy/config/application.rb +26 -0
  71. data/spec/dummy/config/boot.rb +5 -0
  72. data/spec/dummy/config/database.example.yml +14 -0
  73. data/spec/dummy/config/database.yml +13 -0
  74. data/spec/dummy/config/environment.rb +5 -0
  75. data/spec/dummy/config/environments/development.rb +41 -0
  76. data/spec/dummy/config/environments/production.rb +79 -0
  77. data/spec/dummy/config/environments/test.rb +42 -0
  78. data/spec/dummy/config/initializers/assets.rb +11 -0
  79. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  80. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  81. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  82. data/spec/dummy/config/initializers/inflections.rb +16 -0
  83. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  84. data/spec/dummy/config/initializers/session_store.rb +3 -0
  85. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  86. data/spec/dummy/config/locales/en.yml +23 -0
  87. data/spec/dummy/config/routes.rb +3 -0
  88. data/spec/dummy/config/secrets.yml +22 -0
  89. data/spec/dummy/db/schema.rb +246 -0
  90. data/spec/dummy/log/test.log +13097 -0
  91. data/spec/dummy/public/404.html +67 -0
  92. data/spec/dummy/public/422.html +67 -0
  93. data/spec/dummy/public/500.html +66 -0
  94. data/spec/dummy/public/favicon.ico +0 -0
  95. data/spec/factories/accreditation.rb +5 -0
  96. data/spec/factories/adviser.rb +21 -0
  97. data/spec/factories/allowed_payment_method.rb +5 -0
  98. data/spec/factories/firm.rb +34 -0
  99. data/spec/factories/in_person_advice_method.rb +5 -0
  100. data/spec/factories/initial_advice_fee_structure.rb +5 -0
  101. data/spec/factories/initial_meeting_duration.rb +5 -0
  102. data/spec/factories/investment_size.rb +5 -0
  103. data/spec/factories/lookup_firm.rb +6 -0
  104. data/spec/factories/ongoing_advice_fee_structure.rb +5 -0
  105. data/spec/factories/other_advice_method.rb +5 -0
  106. data/spec/factories/principal.rb +15 -0
  107. data/spec/factories/professional_body.rb +5 -0
  108. data/spec/factories/professional_standing.rb +5 -0
  109. data/spec/factories/qualification.rb +5 -0
  110. data/spec/models/accreditation_spec.rb +3 -0
  111. data/spec/models/adviser_spec.rb +93 -0
  112. data/spec/models/allowed_payment_method_spec.rb +3 -0
  113. data/spec/models/firm_spec.rb +188 -0
  114. data/spec/models/in_person_advice_method_spec.rb +3 -0
  115. data/spec/models/initial_advice_fee_structure_spec.rb +3 -0
  116. data/spec/models/initial_meeting_duration_spec.rb +3 -0
  117. data/spec/models/investment_size_spec.rb +3 -0
  118. data/spec/models/lookup/adviser_spec.rb +21 -0
  119. data/spec/models/lookup/firm_spec.rb +19 -0
  120. data/spec/models/ongoing_advice_fee_structure_spec.rb +3 -0
  121. data/spec/models/other_advice_method_spec.rb +3 -0
  122. data/spec/models/principal_spec.rb +185 -0
  123. data/spec/models/qualification_spec.rb +3 -0
  124. data/spec/spec_helper.rb +24 -0
  125. data/spec/support/shared_examples/reference_data.rb +14 -0
  126. metadata +361 -0
@@ -0,0 +1,3 @@
1
+ RSpec.describe AllowedPaymentMethod do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,188 @@
1
+ RSpec.describe Firm do
2
+ subject(:firm) { build(:firm) }
3
+
4
+ describe '#in_person_advice?' do
5
+ context 'when the firm offers in person advice' do
6
+ it 'is true' do
7
+ expect(firm).to be_in_person_advice
8
+ end
9
+ end
10
+
11
+ context 'when the firm does not offer in person advice' do
12
+ it 'is false' do
13
+ firm.in_person_advice_methods.clear
14
+
15
+ expect(firm).to_not be_in_person_advice
16
+ end
17
+ end
18
+ end
19
+
20
+ describe 'subsidaries' do
21
+ context 'when the firm has a parent' do
22
+ it 'is classed as a subsidiary' do
23
+ expect(build(:subsidiary)).to be_subsidiary
24
+ end
25
+ end
26
+
27
+ describe '#subsidiaries' do
28
+ it 'exposes subsidiaries' do
29
+ subsidiary = create(:subsidiary)
30
+ expect(subsidiary.parent.subsidiaries).to contain_exactly(subsidiary)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe 'validation' do
36
+ it 'is valid with valid attributes' do
37
+ expect(firm).to be_valid
38
+ end
39
+
40
+ it 'orders fields correctly for dough' do
41
+ expect(firm.field_order).not_to be_empty
42
+ end
43
+
44
+ describe 'email address' do
45
+ context 'when not present' do
46
+ before { firm.email_address = nil }
47
+
48
+ it { is_expected.to_not be_valid }
49
+ end
50
+
51
+ context 'when badly formatted' do
52
+ before { firm.email_address = 'not-valid' }
53
+
54
+ it { is_expected.to_not be_valid }
55
+ end
56
+ end
57
+
58
+ describe 'telephone number' do
59
+ context 'when not present' do
60
+ before { firm.telephone_number = nil }
61
+
62
+ it { is_expected.to_not be_valid }
63
+ end
64
+
65
+ context 'when badly formatted' do
66
+ before { firm.telephone_number = 'not-valid' }
67
+
68
+ it { is_expected.to_not be_valid }
69
+ end
70
+ end
71
+
72
+ describe 'address line 1' do
73
+ context 'when missing' do
74
+ before { firm.address_line_one = nil }
75
+
76
+ it { is_expected.not_to be_valid }
77
+ end
78
+ end
79
+
80
+ describe 'address town' do
81
+ context 'when missing' do
82
+ before { firm.address_town = nil }
83
+
84
+ it { is_expected.not_to be_valid }
85
+ end
86
+ end
87
+
88
+ describe 'address county' do
89
+ context 'when missing' do
90
+ before { firm.address_county = nil }
91
+
92
+ it { is_expected.not_to be_valid }
93
+ end
94
+ end
95
+
96
+ describe 'address postcode' do
97
+ context 'when missing' do
98
+ before { firm.address_postcode = nil }
99
+
100
+ it { is_expected.not_to be_valid }
101
+ end
102
+
103
+ context 'when invalid' do
104
+ before { firm.address_postcode = nil }
105
+
106
+ it { is_expected.not_to be_valid }
107
+ end
108
+ end
109
+
110
+ describe 'in person advice methods' do
111
+ context 'when none assigned' do
112
+ before { firm.in_person_advice_methods = [] }
113
+
114
+ it { is_expected.to be_valid }
115
+ end
116
+ end
117
+
118
+ describe 'free initial meeting' do
119
+ context 'when missing' do
120
+ before { firm.free_initial_meeting = nil }
121
+
122
+ it { is_expected.not_to be_valid }
123
+ end
124
+
125
+ context 'when set to true' do
126
+ before { firm.free_initial_meeting = true }
127
+
128
+ describe 'initial meeting duration' do
129
+ before { firm.initial_meeting_duration = nil }
130
+
131
+ context 'when missing' do
132
+ it { is_expected.not_to be_valid }
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe 'initial advice fee structures' do
139
+ context 'when none assigned' do
140
+ before { firm.initial_advice_fee_structures = [] }
141
+
142
+ it { is_expected.not_to be_valid }
143
+ end
144
+ end
145
+
146
+ describe 'ongoing advice fee structures' do
147
+ context 'when none assigned' do
148
+ before { firm.ongoing_advice_fee_structures = [] }
149
+
150
+ it { is_expected.not_to be_valid }
151
+ end
152
+ end
153
+
154
+ describe 'allowed payment methods' do
155
+ context 'when none assigned' do
156
+ before { firm.allowed_payment_methods = [] }
157
+
158
+ it { is_expected.not_to be_valid }
159
+ end
160
+ end
161
+
162
+ describe 'minimum fixed fee' do
163
+ context 'when not numeric' do
164
+ before { firm.minimum_fixed_fee = 'not-numeric' }
165
+
166
+ it { is_expected.not_to be_valid }
167
+ end
168
+ end
169
+
170
+ describe 'business income breakdown' do
171
+ context 'when sum not equal to 100' do
172
+ before do
173
+ firm.retirement_income_products_percent = 5
174
+ end
175
+
176
+ it { is_expected.not_to be_valid }
177
+ end
178
+ end
179
+
180
+ describe 'investment size' do
181
+ context 'when none assigned' do
182
+ before { firm.investment_sizes = [] }
183
+
184
+ it { is_expected.not_to be_valid }
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe InPersonAdviceMethod do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe InitialAdviceFeeStructure do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe InitialMeetingDuration do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe InvestmentSize do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,21 @@
1
+ RSpec.describe Lookup::Adviser do
2
+ describe 'validation' do
3
+ it 'is valid with valid attributes' do
4
+ expect(
5
+ described_class.new(reference_number: 'AAA00001', name: 'Ben Lovell')
6
+ ).to be_valid
7
+ end
8
+
9
+ describe 'Reference number rules' do
10
+ it 'must be 8 characters' do
11
+ expect(described_class.new(reference_number: '123A45')).to_not be_valid
12
+ end
13
+ end
14
+
15
+ describe 'Name rules' do
16
+ it 'must be provided' do
17
+ expect(described_class.new(reference_number: 'AAA00001')).to_not be_valid
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ RSpec.describe Lookup::Firm do
2
+ describe 'validation' do
3
+ it 'is valid with valid attributes' do
4
+ expect(
5
+ described_class.new(fca_number: 123456, registered_name: 'Ben Lovell Ltd')
6
+ ).to be_valid
7
+ end
8
+
9
+ describe 'FCA Number rules' do
10
+ it 'accepts numeric' do
11
+ expect(described_class.new(fca_number: '123A45')).to_not be_valid
12
+ end
13
+
14
+ it 'accepts only 6 digits' do
15
+ expect(described_class.new(fca_number: 1234567)).to_not be_valid
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe OngoingAdviceFeeStructure do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.describe OtherAdviceMethod do
2
+ it_behaves_like 'reference data'
3
+ end
@@ -0,0 +1,185 @@
1
+ RSpec.describe Principal do
2
+ let(:principal) { create(:principal) }
3
+
4
+ describe '#lookup_firm' do
5
+ it 'returns my associated lookup firm' do
6
+ expect(principal.lookup_firm).to be
7
+ end
8
+ end
9
+
10
+ describe '#subsidiaries?' do
11
+ context 'when my firm has subsidiaries' do
12
+ before { principal.lookup_firm.subsidiaries.create! }
13
+
14
+ it 'is truthy' do
15
+ expect(principal.subsidiaries?).to be_truthy
16
+ end
17
+ end
18
+
19
+ context 'when my firm has no subsidiaries' do
20
+ it 'is falsey' do
21
+ expect(principal.subsidiaries?).to be_falsey
22
+ end
23
+ end
24
+ end
25
+
26
+ it 'uses the token for ID purposes' do
27
+ expect(principal.id).to eq(principal.token)
28
+ expect(Principal.find(principal.token)).to eq(principal)
29
+ end
30
+
31
+ context 'upon creation' do
32
+ it 'generates an 8 character, 4 byte token' do
33
+ expect(principal.token.length).to eq(8)
34
+ end
35
+
36
+ it 'creates the associated Firm' do
37
+ expect(principal.firm.fca_number).to eq(principal.lookup_firm.fca_number)
38
+ end
39
+ end
40
+
41
+ describe 'validation' do
42
+ it 'is valid with valid attributes' do
43
+ expect(principal).to be_valid
44
+ end
45
+
46
+ it 'must confirm accuracy' do
47
+ expect(build(:principal, confirmed_disclaimer: false)).to_not be_valid
48
+ end
49
+
50
+ describe 'FCA number' do
51
+ it 'must be a present' do
52
+ build(:principal).tap do |p|
53
+ p.fca_number = nil
54
+ expect(p).to_not be_valid
55
+ end
56
+ end
57
+
58
+ it 'must be a 6 digit number' do
59
+ build(:principal).tap do |p|
60
+ p.fca_number = 12345
61
+ expect(p).to_not be_valid
62
+ end
63
+ end
64
+
65
+ it 'must match a `Lookup::Firm`' do
66
+ Lookup::Firm.find_by(fca_number: principal.fca_number).destroy
67
+
68
+ expect(principal).to_not be_valid
69
+ end
70
+
71
+ it 'must be unique' do
72
+ build(:principal).tap do |p|
73
+ p.fca_number = principal.fca_number
74
+ expect(p).to_not be_valid
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'Email address' do
80
+ it 'must be present' do
81
+ expect(build(:principal, email_address: '')).to_not be_valid
82
+ end
83
+
84
+ it 'must be unique' do
85
+ dupe = build(:principal, email_address: principal.email_address)
86
+ expect(dupe).to_not be_valid
87
+ end
88
+
89
+ it 'must be a reasonably valid format' do
90
+ %w(zzz abc@abc a@a.).each do |bad|
91
+ principal.email_address = bad
92
+ expect(principal).to_not be_valid
93
+ end
94
+ end
95
+
96
+ it 'must not exceed 50 characters' do
97
+ long_email = "a@#{'a' * 50}.com"
98
+ expect(build(:principal, email_address: long_email)).to_not be_valid
99
+ end
100
+ end
101
+
102
+ describe 'First name' do
103
+ it 'must be present' do
104
+ expect(build(:principal, first_name: '')).to_not be_valid
105
+ end
106
+
107
+ it 'must be at least 2 characters' do
108
+ expect(build(:principal, first_name: 'A')).to_not be_valid
109
+ end
110
+
111
+ it 'must not exceed 80 characters' do
112
+ expect(build(:principal, first_name: 'A' * 81)).to_not be_valid
113
+ end
114
+ end
115
+
116
+ describe 'Last name' do
117
+ it 'must be present' do
118
+ expect(build(:principal, last_name: '')).to_not be_valid
119
+ end
120
+
121
+ it 'must be at least 2 characters' do
122
+ expect(build(:principal, last_name: 'A')).to_not be_valid
123
+ end
124
+
125
+ it 'must not exceed 80 characters' do
126
+ expect(build(:principal, last_name: 'A' * 81)).to_not be_valid
127
+ end
128
+ end
129
+
130
+ describe 'Job title' do
131
+ it 'must be present' do
132
+ expect(build(:principal, job_title: '')).to_not be_valid
133
+ end
134
+
135
+ it 'must be at least 2 characters' do
136
+ expect(build(:principal, job_title: 'A')).to_not be_valid
137
+ end
138
+
139
+ it 'must not exceed 80 characters' do
140
+ expect(build(:principal, job_title: 'A' * 81)).to_not be_valid
141
+ end
142
+ end
143
+
144
+ describe 'Telephone number' do
145
+ it 'must be present' do
146
+ expect(build(:principal, telephone_number: '')).to_not be_valid
147
+ end
148
+
149
+ it 'must not exceed 50 characters' do
150
+ expect(build(:principal, telephone_number: '1' * 51)).to_not be_valid
151
+ end
152
+
153
+ it 'must contain only digits and spaces' do
154
+ expect(build(:principal, telephone_number: '1 abcd')).to_not be_valid
155
+ end
156
+ end
157
+
158
+ describe 'Website address' do
159
+ context 'when provided' do
160
+ it 'must not exceed 100 characters' do
161
+ expect(build(:principal, website_address: "#{'a' * 100}.com")).not_to be_valid
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ describe 'dough #field_order' do
168
+ let(:fields) do
169
+ [
170
+ :fca_number,
171
+ :website_address,
172
+ :first_name,
173
+ :last_name,
174
+ :job_title,
175
+ :email_address,
176
+ :telephone_number,
177
+ :confirmed_disclaimer
178
+ ]
179
+ end
180
+
181
+ it 'orders fields per the identification form' do
182
+ expect(principal.field_order).to contain_exactly(*fields)
183
+ end
184
+ end
185
+ end