dscf-credit 0.1.4 → 0.1.5
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/app/controllers/concerns/dscf/core/copilot-instructions.md +683 -0
- data/app/controllers/concerns/dscf/core/reviewable_controller.rb +347 -0
- data/app/controllers/dscf/credit/categories_controller.rb +3 -3
- data/app/controllers/dscf/credit/credit_lines_controller.rb +21 -13
- data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +50 -8
- data/app/controllers/dscf/credit/facilitator_applications_controller.rb +35 -0
- data/app/controllers/dscf/credit/facilitators_controller.rb +8 -96
- data/app/controllers/dscf/credit/loan_applications_controller.rb +252 -0
- data/app/controllers/dscf/credit/loan_profiles_controller.rb +61 -68
- data/app/controllers/dscf/credit/payment_requests_controller.rb +3 -5
- data/app/controllers/dscf/credit/scoring_parameters_controller.rb +59 -13
- data/app/controllers/dscf/credit/system_configs_controller.rb +30 -12
- data/app/models/concerns/core/reviewable_model.rb +31 -0
- data/app/models/dscf/credit/bank.rb +3 -3
- data/app/models/dscf/credit/bank_branch.rb +1 -1
- data/app/models/dscf/credit/category.rb +1 -2
- data/app/models/dscf/credit/credit_line.rb +4 -10
- data/app/models/dscf/credit/eligible_credit_line.rb +2 -2
- data/app/models/dscf/credit/facilitator.rb +6 -17
- data/app/models/dscf/credit/facilitator_application.rb +20 -0
- data/app/models/dscf/credit/loan_application.rb +30 -0
- data/app/models/dscf/credit/loan_profile.rb +10 -30
- data/app/models/dscf/credit/parameter_normalizer.rb +1 -1
- data/app/models/dscf/credit/scoring_parameter.rb +5 -7
- data/app/models/dscf/credit/system_config.rb +4 -9
- data/app/serializers/dscf/credit/category_serializer.rb +0 -1
- data/app/serializers/dscf/credit/credit_line_serializer.rb +2 -2
- data/app/serializers/dscf/credit/facilitator_application_serializer.rb +7 -0
- data/app/serializers/dscf/credit/facilitator_serializer.rb +3 -6
- data/app/serializers/dscf/credit/loan_application_serializer.rb +12 -0
- data/app/serializers/dscf/credit/loan_profile_serializer.rb +3 -6
- data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +3 -4
- data/app/serializers/dscf/credit/system_config_serializer.rb +2 -2
- data/app/services/dscf/credit/credit_scoring_engine.rb +258 -0
- data/app/services/dscf/credit/facility_limit_calculation_engine.rb +159 -0
- data/app/services/dscf/credit/loan_profile_creation_service.rb +91 -0
- data/app/services/dscf/credit/risk_application_service.rb +61 -11
- data/config/locales/en.yml +63 -48
- data/config/routes.rb +31 -17
- data/db/migrate/20250822091131_create_dscf_credit_credit_lines.rb +1 -8
- data/db/migrate/20250822091820_create_dscf_credit_system_configs.rb +0 -7
- data/db/migrate/20250822092050_create_dscf_credit_scoring_parameters.rb +2 -6
- data/db/migrate/20250822092225_create_dscf_credit_parameter_normalizers.rb +1 -1
- data/db/migrate/20250822092236_create_dscf_credit_loan_applications.rb +20 -0
- data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +7 -19
- data/db/migrate/20250822092426_create_dscf_credit_facilitator_applications.rb +10 -0
- data/db/migrate/20250822092436_create_dscf_credit_facilitators.rb +1 -16
- data/db/seeds.rb +316 -203
- data/lib/dscf/credit/version.rb +1 -1
- data/spec/factories/dscf/credit/banks.rb +1 -1
- data/spec/factories/dscf/credit/credit_lines.rb +0 -23
- data/spec/factories/dscf/credit/facilitator_applications.rb +37 -0
- data/spec/factories/dscf/credit/facilitators.rb +8 -30
- data/spec/factories/dscf/credit/loan_applications.rb +42 -0
- data/spec/factories/dscf/credit/loan_profiles.rb +20 -34
- data/spec/factories/dscf/credit/parameter_normalizers.rb +4 -4
- data/spec/factories/dscf/credit/scoring_parameters.rb +14 -11
- data/spec/factories/dscf/credit/system_configs.rb +21 -5
- metadata +20 -10
- data/app/controllers/concerns/dscf/credit/reviewable.rb +0 -112
- data/app/controllers/dscf/credit/scoring_tables_controller.rb +0 -63
- data/app/models/dscf/credit/scoring_table.rb +0 -24
- data/app/serializers/dscf/credit/scoring_table_serializer.rb +0 -9
- data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +0 -18
- data/spec/factories/dscf/credit/scoring_tables.rb +0 -25
data/db/seeds.rb
CHANGED
@@ -146,56 +146,49 @@ end
|
|
146
146
|
|
147
147
|
# 1. Banks (independent)
|
148
148
|
puts "Seeding banks..."
|
149
|
-
|
150
|
-
bank.name = '
|
151
|
-
bank.swift_code = '
|
149
|
+
bunna_bank = Dscf::Credit::Bank.find_or_create_by(registration_number: 'BUN001') do |bank|
|
150
|
+
bank.name = 'Bunna Bank'
|
151
|
+
bank.swift_code = 'BUNNETAA'
|
152
152
|
bank.headquarters_address = 'Addis Ababa, Ethiopia'
|
153
153
|
bank.city = 'Addis Ababa'
|
154
154
|
bank.country = 'Ethiopia'
|
155
|
-
bank.contact_email = 'info@
|
155
|
+
bank.contact_email = 'info@bunnabank.com'
|
156
156
|
bank.contact_phone = '+251115510000'
|
157
157
|
bank.status = 'active'
|
158
158
|
end
|
159
159
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
bank.headquarters_address = 'Addis Ababa, Ethiopia'
|
164
|
-
bank.city = 'Addis Ababa'
|
165
|
-
bank.country = 'Ethiopia'
|
166
|
-
bank.contact_email = 'info@awashbank.com'
|
167
|
-
bank.contact_phone = '+251115524000'
|
168
|
-
bank.status = 'active'
|
169
|
-
end
|
160
|
+
# Use the same bank for all operations
|
161
|
+
bank1 = bunna_bank
|
162
|
+
bank2 = bunna_bank
|
170
163
|
|
171
164
|
# 2. Bank Branches (depends on banks)
|
172
165
|
puts "Seeding bank branches..."
|
173
|
-
|
174
|
-
branch.branch_code = '
|
166
|
+
bunna_head_office = Dscf::Credit::BankBranch.find_or_create_by(bank: bunna_bank, branch_name: 'Head Office') do |branch|
|
167
|
+
branch.branch_code = 'BUN-HO-001'
|
175
168
|
branch.branch_address = 'Churchill Avenue, Addis Ababa'
|
176
169
|
branch.city = 'Addis Ababa'
|
177
170
|
branch.country = 'Ethiopia'
|
178
|
-
branch.contact_email = 'headoffice@
|
171
|
+
branch.contact_email = 'headoffice@bunnabank.com'
|
179
172
|
branch.contact_phone = '+251115510001'
|
180
173
|
branch.status = 'active'
|
181
174
|
end
|
182
175
|
|
183
|
-
Dscf::Credit::BankBranch.find_or_create_by(bank:
|
184
|
-
branch.branch_code = '
|
176
|
+
Dscf::Credit::BankBranch.find_or_create_by(bank: bunna_bank, branch_name: 'Merkato Branch') do |branch|
|
177
|
+
branch.branch_code = 'BUN-MER-002'
|
185
178
|
branch.branch_address = 'Merkato, Addis Ababa'
|
186
179
|
branch.city = 'Addis Ababa'
|
187
180
|
branch.country = 'Ethiopia'
|
188
|
-
branch.contact_email = 'merkato@
|
181
|
+
branch.contact_email = 'merkato@bunnabank.com'
|
189
182
|
branch.contact_phone = '+251115510002'
|
190
183
|
branch.status = 'active'
|
191
184
|
end
|
192
185
|
|
193
|
-
Dscf::Credit::BankBranch.find_or_create_by(bank:
|
194
|
-
branch.branch_code = '
|
195
|
-
branch.branch_address = '
|
186
|
+
Dscf::Credit::BankBranch.find_or_create_by(bank: bunna_bank, branch_name: 'Bole Branch') do |branch|
|
187
|
+
branch.branch_code = 'BUN-BOL-003'
|
188
|
+
branch.branch_address = 'Bole Road, Addis Ababa'
|
196
189
|
branch.city = 'Addis Ababa'
|
197
190
|
branch.country = 'Ethiopia'
|
198
|
-
branch.contact_email = '
|
191
|
+
branch.contact_email = 'bole@bunnabank.com'
|
199
192
|
branch.contact_phone = '+251115524001'
|
200
193
|
branch.status = 'active'
|
201
194
|
end
|
@@ -204,66 +197,66 @@ end
|
|
204
197
|
puts "Seeding bank staff..."
|
205
198
|
|
206
199
|
# Get bank branches
|
207
|
-
|
208
|
-
|
209
|
-
|
200
|
+
bunna_head_office_branch = Dscf::Credit::BankBranch.find_by(bank: bunna_bank, branch_name: 'Head Office')
|
201
|
+
bunna_merkato_branch = Dscf::Credit::BankBranch.find_by(bank: bunna_bank, branch_name: 'Merkato Branch')
|
202
|
+
bunna_bole_branch = Dscf::Credit::BankBranch.find_by(bank: bunna_bank, branch_name: 'Bole Branch')
|
210
203
|
|
211
204
|
# Create bank staff only if we have users from dscf-core
|
212
205
|
if defined?(Dscf::Core::User) && Dscf::Core::User.exists?
|
213
206
|
users = Dscf::Core::User.limit(6)
|
214
207
|
|
215
|
-
#
|
216
|
-
if
|
208
|
+
# Bunna Head Office Staff
|
209
|
+
if bunna_head_office_branch && users.first
|
217
210
|
Dscf::Credit::BankStaff.find_or_create_by(
|
218
211
|
user: users.first,
|
219
|
-
bank_branch:
|
212
|
+
bank_branch: bunna_head_office_branch
|
220
213
|
) do |staff|
|
221
214
|
staff.status = 'active'
|
222
215
|
end
|
223
216
|
end
|
224
217
|
|
225
|
-
if
|
218
|
+
if bunna_head_office_branch && users.second
|
226
219
|
Dscf::Credit::BankStaff.find_or_create_by(
|
227
220
|
user: users.second,
|
228
|
-
bank_branch:
|
221
|
+
bank_branch: bunna_head_office_branch
|
229
222
|
) do |staff|
|
230
223
|
staff.status = 'active'
|
231
224
|
end
|
232
225
|
end
|
233
226
|
|
234
|
-
#
|
235
|
-
if
|
227
|
+
# Bunna Merkato Branch Staff
|
228
|
+
if bunna_merkato_branch && users.third
|
236
229
|
Dscf::Credit::BankStaff.find_or_create_by(
|
237
230
|
user: users.third,
|
238
|
-
bank_branch:
|
231
|
+
bank_branch: bunna_merkato_branch
|
239
232
|
) do |staff|
|
240
233
|
staff.status = 'active'
|
241
234
|
end
|
242
235
|
end
|
243
236
|
|
244
|
-
if
|
237
|
+
if bunna_merkato_branch && users.fourth
|
245
238
|
Dscf::Credit::BankStaff.find_or_create_by(
|
246
239
|
user: users.fourth,
|
247
|
-
bank_branch:
|
240
|
+
bank_branch: bunna_merkato_branch
|
248
241
|
) do |staff|
|
249
242
|
staff.status = 'active'
|
250
243
|
end
|
251
244
|
end
|
252
245
|
|
253
|
-
#
|
254
|
-
if
|
246
|
+
# Bunna Bole Branch Staff
|
247
|
+
if bunna_bole_branch && users.fifth
|
255
248
|
Dscf::Credit::BankStaff.find_or_create_by(
|
256
249
|
user: users.fifth,
|
257
|
-
bank_branch:
|
250
|
+
bank_branch: bunna_bole_branch
|
258
251
|
) do |staff|
|
259
252
|
staff.status = 'active'
|
260
253
|
end
|
261
254
|
end
|
262
255
|
|
263
|
-
if
|
256
|
+
if bunna_bole_branch && users[5]
|
264
257
|
Dscf::Credit::BankStaff.find_or_create_by(
|
265
258
|
user: users[5],
|
266
|
-
bank_branch:
|
259
|
+
bank_branch: bunna_bole_branch
|
267
260
|
) do |staff|
|
268
261
|
staff.status = 'active'
|
269
262
|
end
|
@@ -275,7 +268,7 @@ end
|
|
275
268
|
# 4. System Config Definitions (depends on banks)
|
276
269
|
puts "Seeding system config definitions..."
|
277
270
|
config_def1 = Dscf::Credit::SystemConfigDefinition.find_or_create_by(
|
278
|
-
bank:
|
271
|
+
bank: bunna_bank,
|
279
272
|
config_key: 'max_loan_amount'
|
280
273
|
) do |config|
|
281
274
|
config.description = 'Maximum loan amount allowed per transaction'
|
@@ -284,7 +277,7 @@ config_def1 = Dscf::Credit::SystemConfigDefinition.find_or_create_by(
|
|
284
277
|
end
|
285
278
|
|
286
279
|
config_def2 = Dscf::Credit::SystemConfigDefinition.find_or_create_by(
|
287
|
-
bank:
|
280
|
+
bank: bunna_bank,
|
288
281
|
config_key: 'interest_calculation_method'
|
289
282
|
) do |config|
|
290
283
|
config.description = 'Method used for calculating interest'
|
@@ -293,7 +286,7 @@ config_def2 = Dscf::Credit::SystemConfigDefinition.find_or_create_by(
|
|
293
286
|
end
|
294
287
|
|
295
288
|
config_def3 = Dscf::Credit::SystemConfigDefinition.find_or_create_by(
|
296
|
-
bank:
|
289
|
+
bank: bunna_bank,
|
297
290
|
config_key: 'max_loan_term_days'
|
298
291
|
) do |config|
|
299
292
|
config.description = 'Maximum loan term in days'
|
@@ -303,28 +296,48 @@ end
|
|
303
296
|
|
304
297
|
# 4. System Configs (depends on system config definitions)
|
305
298
|
puts "Seeding system configs..."
|
306
|
-
Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def1) do |config|
|
299
|
+
system_config1 = Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def1) do |config|
|
307
300
|
config.config_value = '500000.00'
|
308
|
-
config.status = 'approved'
|
309
|
-
config.reviewed_by = admin_user
|
310
|
-
config.review_date = Time.current
|
311
301
|
config.last_updated_by = admin_user
|
312
302
|
end
|
313
303
|
|
314
|
-
|
304
|
+
# Create approved review for system_config1
|
305
|
+
Dscf::Core::Review.find_or_create_by(
|
306
|
+
reviewable: system_config1,
|
307
|
+
reviewed_by: admin_user
|
308
|
+
) do |review|
|
309
|
+
review.status = 'approved'
|
310
|
+
review.reviewed_at = Time.current
|
311
|
+
end
|
312
|
+
|
313
|
+
system_config2 = Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def2) do |config|
|
315
314
|
config.config_value = 'daily'
|
316
|
-
config.status = 'approved'
|
317
|
-
config.reviewed_by = admin_user
|
318
|
-
config.review_date = Time.current
|
319
315
|
config.last_updated_by = admin_user
|
320
316
|
end
|
321
317
|
|
322
|
-
|
318
|
+
# Create approved review for system_config2
|
319
|
+
Dscf::Core::Review.find_or_create_by(
|
320
|
+
reviewable: system_config2,
|
321
|
+
reviewed_by: admin_user
|
322
|
+
) do |review|
|
323
|
+
review.status = 'approved'
|
324
|
+
review.reviewed_at = Time.current
|
325
|
+
end
|
326
|
+
|
327
|
+
system_config3 = Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def3) do |config|
|
323
328
|
config.config_value = '180'
|
324
|
-
config.status = 'pending'
|
325
329
|
config.last_updated_by = bank_admin
|
326
330
|
end
|
327
331
|
|
332
|
+
# Create pending review for system_config3
|
333
|
+
Dscf::Core::Review.find_or_create_by(
|
334
|
+
reviewable: system_config3,
|
335
|
+
reviewed_by: bank_admin
|
336
|
+
) do |review|
|
337
|
+
review.status = 'pending'
|
338
|
+
review.reviewed_at = Time.current
|
339
|
+
end
|
340
|
+
|
328
341
|
# 4.5. Categories (independent)
|
329
342
|
puts "Seeding categories..."
|
330
343
|
sme_category = Dscf::Credit::Category.find_or_create_by(type: 'credit_line', name: 'SME') do |category|
|
@@ -374,33 +387,25 @@ end
|
|
374
387
|
|
375
388
|
# 5. Credit Lines (depends on banks, users, and categories)
|
376
389
|
puts "Seeding credit lines..."
|
377
|
-
credit_line1 = Dscf::Credit::CreditLine.find_or_create_by(bank:
|
390
|
+
credit_line1 = Dscf::Credit::CreditLine.find_or_create_by(bank: bunna_bank, name: 'SME Credit Line') do |line|
|
378
391
|
line.category = sme_category
|
379
|
-
line.code = '
|
392
|
+
line.code = 'BUN-SME-001'
|
380
393
|
line.description = 'Credit line for Small and Medium Enterprises'
|
381
|
-
line.status = 'approved'
|
382
394
|
line.created_by = admin_user
|
383
|
-
line.reviewed_by = bank_admin
|
384
|
-
line.review_date = 1.week.ago
|
385
395
|
end
|
386
396
|
|
387
|
-
credit_line2 = Dscf::Credit::CreditLine.find_or_create_by(bank:
|
397
|
+
credit_line2 = Dscf::Credit::CreditLine.find_or_create_by(bank: bunna_bank, name: 'Personal Credit Line') do |line|
|
388
398
|
line.category = personal_category
|
389
|
-
line.code = '
|
399
|
+
line.code = 'BUN-PER-002'
|
390
400
|
line.description = 'Personal credit line for individuals'
|
391
|
-
line.status = 'approved'
|
392
401
|
line.created_by = admin_user
|
393
|
-
line.reviewed_by = bank_admin
|
394
|
-
line.review_date = 5.days.ago
|
395
402
|
end
|
396
403
|
|
397
|
-
Dscf::Credit::CreditLine.find_or_create_by(bank:
|
404
|
+
Dscf::Credit::CreditLine.find_or_create_by(bank: bunna_bank, name: 'Agricultural Credit Line') do |line|
|
398
405
|
line.category = agricultural_category
|
399
|
-
line.code = '
|
406
|
+
line.code = 'BUN-AGR-001'
|
400
407
|
line.description = 'Credit line for agricultural sector'
|
401
|
-
line.status = 'pending'
|
402
408
|
line.created_by = bank_admin
|
403
|
-
line.reviewed_by = admin_user
|
404
409
|
end
|
405
410
|
|
406
411
|
# 6. Credit Line Specs (depends on credit lines)
|
@@ -443,10 +448,10 @@ Dscf::Credit::CreditLineSpec.find_or_create_by(credit_line: credit_line2) do |sp
|
|
443
448
|
spec.created_by = admin_user
|
444
449
|
end
|
445
450
|
|
446
|
-
# 7. Scoring Parameters
|
451
|
+
# 7. Scoring Parameters
|
447
452
|
puts "Seeding scoring parameters..."
|
448
453
|
scoring_param1 = Dscf::Credit::ScoringParameter.find_or_create_by(
|
449
|
-
bank:
|
454
|
+
bank: bunna_bank,
|
450
455
|
name: 'Monthly Income'
|
451
456
|
) do |param|
|
452
457
|
param.description = 'Monthly income of the applicant'
|
@@ -455,17 +460,24 @@ scoring_param1 = Dscf::Credit::ScoringParameter.find_or_create_by(
|
|
455
460
|
param.min_value = 0
|
456
461
|
param.max_value = 1000000
|
457
462
|
param.active = true
|
458
|
-
param.status = 'approved'
|
459
|
-
param.reviewed_by = admin_user
|
460
|
-
param.review_date = Time.current
|
461
463
|
param.created_by = admin_user
|
464
|
+
param.category = personal_category
|
462
465
|
param.source = 'internal'
|
463
466
|
param.scoring_param_type = consumer_type
|
464
467
|
param.document_reference = 'DOC-SP-001'
|
465
468
|
end
|
466
469
|
|
470
|
+
# Create approved review for scoring_param1
|
471
|
+
Dscf::Core::Review.find_or_create_by(
|
472
|
+
reviewable: scoring_param1,
|
473
|
+
reviewed_by: admin_user
|
474
|
+
) do |review|
|
475
|
+
review.status = 'approved'
|
476
|
+
review.reviewed_at = Time.current
|
477
|
+
end
|
478
|
+
|
467
479
|
scoring_param2 = Dscf::Credit::ScoringParameter.find_or_create_by(
|
468
|
-
bank:
|
480
|
+
bank: bunna_bank,
|
469
481
|
name: 'Credit History Score'
|
470
482
|
) do |param|
|
471
483
|
param.description = 'Credit history score from credit bureau'
|
@@ -474,36 +486,50 @@ scoring_param2 = Dscf::Credit::ScoringParameter.find_or_create_by(
|
|
474
486
|
param.min_value = 300
|
475
487
|
param.max_value = 850
|
476
488
|
param.active = true
|
477
|
-
param.status = 'approved'
|
478
|
-
param.reviewed_by = admin_user
|
479
|
-
param.review_date = Time.current
|
480
489
|
param.created_by = admin_user
|
490
|
+
param.category = personal_category
|
481
491
|
param.source = 'external'
|
482
492
|
param.scoring_param_type = consumer_type
|
483
493
|
param.document_reference = 'DOC-SP-002'
|
484
494
|
end
|
485
495
|
|
496
|
+
# Create approved review for scoring_param2
|
497
|
+
Dscf::Core::Review.find_or_create_by(
|
498
|
+
reviewable: scoring_param2,
|
499
|
+
reviewed_by: admin_user
|
500
|
+
) do |review|
|
501
|
+
review.status = 'approved'
|
502
|
+
review.reviewed_at = Time.current
|
503
|
+
end
|
504
|
+
|
486
505
|
scoring_param3 = Dscf::Credit::ScoringParameter.find_or_create_by(
|
487
|
-
bank:
|
506
|
+
bank: bunna_bank,
|
488
507
|
name: 'Employment Type'
|
489
508
|
) do |param|
|
490
509
|
param.description = 'Type of employment (permanent, contract, self-employed)'
|
491
510
|
param.data_type = 'string'
|
492
511
|
param.weight = 0.2
|
493
512
|
param.active = true
|
494
|
-
param.status = 'approved'
|
495
|
-
param.reviewed_by = bank_admin
|
496
|
-
param.review_date = Time.current
|
497
513
|
param.created_by = admin_user
|
514
|
+
param.category = personal_category
|
498
515
|
param.source = 'internal'
|
499
516
|
param.scoring_param_type = consumer_type
|
500
517
|
param.document_reference = 'DOC-SP-003'
|
501
518
|
end
|
502
519
|
|
520
|
+
# Create approved review for scoring_param3
|
521
|
+
Dscf::Core::Review.find_or_create_by(
|
522
|
+
reviewable: scoring_param3,
|
523
|
+
reviewed_by: bank_admin
|
524
|
+
) do |review|
|
525
|
+
review.status = 'approved'
|
526
|
+
review.reviewed_at = Time.current
|
527
|
+
end
|
528
|
+
|
503
529
|
# 8. Parameter Normalizers (depends on scoring parameters)
|
504
530
|
puts "Seeding parameter normalizers..."
|
505
531
|
# Ensure we have the scoring parameter reference
|
506
|
-
employment_param = Dscf::Credit::ScoringParameter.find_by(bank:
|
532
|
+
employment_param = Dscf::Credit::ScoringParameter.find_by(bank: bunna_bank, name: 'Employment Type')
|
507
533
|
|
508
534
|
Dscf::Credit::ParameterNormalizer.find_or_create_by(
|
509
535
|
scoring_parameter: employment_param,
|
@@ -532,131 +558,217 @@ Dscf::Credit::ParameterNormalizer.find_or_create_by(
|
|
532
558
|
normalizer.normalized_value = 0.6
|
533
559
|
end
|
534
560
|
|
535
|
-
#
|
536
|
-
puts "Seeding
|
537
|
-
#
|
538
|
-
|
539
|
-
credit_history_param = Dscf::Credit::ScoringParameter.find_by(bank: bank1, name: 'Credit History Score')
|
540
|
-
employment_param = Dscf::Credit::ScoringParameter.find_by(bank: bank1, name: 'Employment Type')
|
541
|
-
|
542
|
-
# Create scoring tables for credit_line1 (SME Credit Line)
|
543
|
-
if monthly_income_param
|
544
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
545
|
-
category: sme_category,
|
546
|
-
scoring_parameter: monthly_income_param
|
547
|
-
) do |scoring_table|
|
548
|
-
scoring_table.weight = 0.4
|
549
|
-
scoring_table.active = true
|
550
|
-
scoring_table.created_by = admin_user
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
|
-
if credit_history_param
|
555
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
556
|
-
category: sme_category,
|
557
|
-
scoring_parameter: credit_history_param
|
558
|
-
) do |scoring_table|
|
559
|
-
scoring_table.weight = 0.35
|
560
|
-
scoring_table.active = true
|
561
|
-
scoring_table.created_by = admin_user
|
562
|
-
end
|
563
|
-
end
|
564
|
-
|
565
|
-
if employment_param
|
566
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
567
|
-
category: sme_category,
|
568
|
-
scoring_parameter: employment_param
|
569
|
-
) do |scoring_table|
|
570
|
-
scoring_table.weight = 0.25
|
571
|
-
scoring_table.active = true
|
572
|
-
scoring_table.created_by = admin_user
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
|
-
# Create scoring tables for credit_line2 (Personal Credit Line)
|
577
|
-
if monthly_income_param
|
578
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
579
|
-
category: personal_category,
|
580
|
-
scoring_parameter: monthly_income_param
|
581
|
-
) do |scoring_table|
|
582
|
-
scoring_table.weight = 0.5
|
583
|
-
scoring_table.active = true
|
584
|
-
scoring_table.created_by = admin_user
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
if credit_history_param
|
589
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
590
|
-
category: personal_category,
|
591
|
-
scoring_parameter: credit_history_param
|
592
|
-
) do |scoring_table|
|
593
|
-
scoring_table.weight = 0.3
|
594
|
-
scoring_table.active = true
|
595
|
-
scoring_table.created_by = admin_user
|
596
|
-
end
|
597
|
-
end
|
598
|
-
|
599
|
-
if employment_param
|
600
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
601
|
-
category: personal_category,
|
602
|
-
scoring_parameter: employment_param
|
603
|
-
) do |scoring_table|
|
604
|
-
scoring_table.weight = 0.2
|
605
|
-
scoring_table.active = true
|
606
|
-
scoring_table.created_by = admin_user
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
# Create scoring tables for eligibility_category
|
611
|
-
if monthly_income_param
|
612
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
613
|
-
category: eligibility_category,
|
614
|
-
scoring_parameter: monthly_income_param
|
615
|
-
) do |scoring_table|
|
616
|
-
scoring_table.weight = 0.4
|
617
|
-
scoring_table.active = true
|
618
|
-
scoring_table.created_by = admin_user
|
619
|
-
end
|
620
|
-
end
|
621
|
-
|
622
|
-
if credit_history_param
|
623
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
624
|
-
category: eligibility_category,
|
625
|
-
scoring_parameter: credit_history_param
|
626
|
-
) do |scoring_table|
|
627
|
-
scoring_table.weight = 0.35
|
628
|
-
scoring_table.active = true
|
629
|
-
scoring_table.created_by = admin_user
|
630
|
-
end
|
631
|
-
end
|
632
|
-
|
633
|
-
if employment_param
|
634
|
-
Dscf::Credit::ScoringTable.find_or_create_by(
|
635
|
-
category: eligibility_category,
|
636
|
-
scoring_parameter: employment_param
|
637
|
-
) do |scoring_table|
|
638
|
-
scoring_table.weight = 0.25
|
639
|
-
scoring_table.active = true
|
640
|
-
scoring_table.created_by = admin_user
|
641
|
-
end
|
642
|
-
end
|
561
|
+
# 9. Loan Profiles (depends on loan applications)
|
562
|
+
puts "Seeding loan profiles..."
|
563
|
+
# Note: Loan profiles will be created after loan applications are seeded
|
564
|
+
# For now, we'll create them with placeholder loan_application_id and update later
|
643
565
|
|
644
|
-
#
|
566
|
+
# 10. Loan Profile Scoring Specs (depends on loan profiles)
|
567
|
+
puts "Seeding loan profile scoring specs..."
|
568
|
+
# Note: This will be moved after loan profiles are created
|
569
|
+
|
570
|
+
# 10.5. Loan Applications (depends on banks, users, and bank branches)
|
571
|
+
puts "Seeding loan applications..."
|
572
|
+
loan_application1 = Dscf::Credit::LoanApplication.find_or_create_by(
|
573
|
+
bank: bunna_bank,
|
574
|
+
user_id: user2.id,
|
575
|
+
review_branch: bunna_head_office
|
576
|
+
) do |application|
|
577
|
+
application.backer = user1
|
578
|
+
application.bank_statement_source = "internal"
|
579
|
+
application.user_info = {
|
580
|
+
name: "Jane Smith",
|
581
|
+
phone: "+251922334455",
|
582
|
+
email: "jane.smith@example.com",
|
583
|
+
address: "123 Main St, Addis Ababa",
|
584
|
+
id_number: "ID123456789",
|
585
|
+
date_of_birth: "1985-05-15"
|
586
|
+
}
|
587
|
+
application.facilitator_info = {
|
588
|
+
business_name: "ABC Trading Company",
|
589
|
+
license_number: "LIC001234",
|
590
|
+
business_type: "retail",
|
591
|
+
years_in_business: 5,
|
592
|
+
monthly_turnover: 150000.00
|
593
|
+
}
|
594
|
+
application.bank_info = {
|
595
|
+
account_number: "123456789012",
|
596
|
+
account_holder: "Jane Smith",
|
597
|
+
bank_name: "Bunna Bank",
|
598
|
+
branch_name: "Head Office"
|
599
|
+
}
|
600
|
+
application.field_assessment = {
|
601
|
+
credit_score: 720,
|
602
|
+
risk_level: "medium",
|
603
|
+
recommendation: "approved",
|
604
|
+
assessed_by: "Field Officer A",
|
605
|
+
assessment_date: Time.current.iso8601
|
606
|
+
}
|
607
|
+
end
|
608
|
+
|
609
|
+
# Create approved review for loan_application1
|
610
|
+
Dscf::Core::Review.find_or_create_by(
|
611
|
+
reviewable: loan_application1,
|
612
|
+
reviewed_by: admin_user
|
613
|
+
) do |review|
|
614
|
+
review.status = 'approved'
|
615
|
+
review.reviewed_at = Time.current
|
616
|
+
end
|
617
|
+
|
618
|
+
loan_application2 = Dscf::Credit::LoanApplication.find_or_create_by(
|
619
|
+
bank: bunna_bank,
|
620
|
+
user_id: user3.id,
|
621
|
+
review_branch: bunna_merkato_branch
|
622
|
+
) do |application|
|
623
|
+
application.backer = user1
|
624
|
+
application.bank_statement_source = "external"
|
625
|
+
application.user_info = {
|
626
|
+
name: "Mike Johnson",
|
627
|
+
phone: "+251933445566",
|
628
|
+
email: "mike.johnson@example.com",
|
629
|
+
address: "456 Oak Ave, Addis Ababa",
|
630
|
+
id_number: "ID987654321",
|
631
|
+
date_of_birth: "1980-12-10"
|
632
|
+
}
|
633
|
+
application.facilitator_info = {
|
634
|
+
business_name: "XYZ Wholesale",
|
635
|
+
license_number: "LIC005678",
|
636
|
+
business_type: "wholesale",
|
637
|
+
years_in_business: 8,
|
638
|
+
monthly_turnover: 500000.00
|
639
|
+
}
|
640
|
+
application.bank_info = {
|
641
|
+
account_number: "987654321098",
|
642
|
+
account_holder: "Mike Johnson",
|
643
|
+
bank_name: "Commercial Bank",
|
644
|
+
branch_name: "Main Branch"
|
645
|
+
}
|
646
|
+
application.field_assessment = {
|
647
|
+
credit_score: 650,
|
648
|
+
risk_level: "high",
|
649
|
+
recommendation: "conditional_approval",
|
650
|
+
assessed_by: "Field Officer B",
|
651
|
+
assessment_date: Time.current.iso8601
|
652
|
+
}
|
653
|
+
application.score = 65.0
|
654
|
+
end
|
655
|
+
|
656
|
+
# Create pending review for loan_application2
|
657
|
+
Dscf::Core::Review.find_or_create_by(
|
658
|
+
reviewable: loan_application2,
|
659
|
+
reviewed_by: bank_admin
|
660
|
+
) do |review|
|
661
|
+
review.status = 'pending'
|
662
|
+
review.reviewed_at = Time.current
|
663
|
+
end
|
664
|
+
|
665
|
+
# 10.6. Facilitator Applications (depends on users and banks)
|
666
|
+
puts "Seeding facilitator applications..."
|
667
|
+
facilitator_application1 = Dscf::Credit::FacilitatorApplication.find_or_create_by(
|
668
|
+
user: user4,
|
669
|
+
bank: bunna_bank
|
670
|
+
) do |application|
|
671
|
+
application.facilitator_info = {
|
672
|
+
business_name: "Global Trade Solutions",
|
673
|
+
contact_person: "Ahmed Hassan",
|
674
|
+
phone: "+251911223344",
|
675
|
+
email: "ahmed@globaltrade.et",
|
676
|
+
address: "789 Commerce St, Addis Ababa",
|
677
|
+
business_type: "import_export",
|
678
|
+
license_number: "LIC789012",
|
679
|
+
years_in_business: 7,
|
680
|
+
monthly_turnover: 200000.00,
|
681
|
+
number_of_employees: 15,
|
682
|
+
business_registration_date: "2017-03-15",
|
683
|
+
tax_identification_number: "TIN123456789",
|
684
|
+
bank_account_details: {
|
685
|
+
bank_name: "Bunna Bank",
|
686
|
+
account_number: "555666777888",
|
687
|
+
account_holder: "Global Trade Solutions"
|
688
|
+
}
|
689
|
+
}
|
690
|
+
end
|
691
|
+
|
692
|
+
# Create approved review for facilitator_application1
|
693
|
+
Dscf::Core::Review.find_or_create_by(
|
694
|
+
reviewable: facilitator_application1,
|
695
|
+
reviewed_by: admin_user
|
696
|
+
) do |review|
|
697
|
+
review.status = 'approved'
|
698
|
+
review.reviewed_at = Time.current
|
699
|
+
end
|
700
|
+
|
701
|
+
facilitator_application2 = Dscf::Credit::FacilitatorApplication.find_or_create_by(
|
702
|
+
user: user3,
|
703
|
+
bank: bunna_bank
|
704
|
+
) do |application|
|
705
|
+
application.facilitator_info = {
|
706
|
+
business_name: "Ethiopian Commodities Ltd",
|
707
|
+
contact_person: "Sara Mengistu",
|
708
|
+
phone: "+251922334455",
|
709
|
+
email: "sara@ethcommodities.et",
|
710
|
+
address: "321 Market Ave, Addis Ababa",
|
711
|
+
business_type: "commodities_trading",
|
712
|
+
license_number: "LIC345678",
|
713
|
+
years_in_business: 5,
|
714
|
+
monthly_turnover: 150000.00,
|
715
|
+
number_of_employees: 8,
|
716
|
+
business_registration_date: "2019-08-22",
|
717
|
+
tax_identification_number: "TIN987654321",
|
718
|
+
bank_account_details: {
|
719
|
+
bank_name: "Commercial Bank",
|
720
|
+
account_number: "111222333444",
|
721
|
+
account_holder: "Ethiopian Commodities Ltd"
|
722
|
+
}
|
723
|
+
}
|
724
|
+
end
|
725
|
+
|
726
|
+
# Create pending review for facilitator_application2
|
727
|
+
Dscf::Core::Review.find_or_create_by(
|
728
|
+
reviewable: facilitator_application2,
|
729
|
+
reviewed_by: bank_admin
|
730
|
+
) do |review|
|
731
|
+
review.status = 'pending'
|
732
|
+
review.reviewed_at = Time.current
|
733
|
+
end
|
734
|
+
|
735
|
+
# 10.7. Facilitators (depends on facilitator applications)
|
736
|
+
puts "Seeding facilitators..."
|
737
|
+
facilitator1 = Dscf::Credit::Facilitator.find_or_create_by(
|
738
|
+
facilitator_application: facilitator_application1
|
739
|
+
) do |facilitator|
|
740
|
+
facilitator.total_limit = 500000.00
|
741
|
+
end
|
742
|
+
|
743
|
+
# Create approved review for facilitator1
|
744
|
+
Dscf::Core::Review.find_or_create_by(
|
745
|
+
reviewable: facilitator1,
|
746
|
+
reviewed_by: admin_user
|
747
|
+
) do |review|
|
748
|
+
review.status = 'approved'
|
749
|
+
review.reviewed_at = Time.current
|
750
|
+
end
|
751
|
+
|
752
|
+
# 11. Loan Profiles (depends on loan applications)
|
645
753
|
puts "Seeding loan profiles..."
|
646
754
|
loan_profile1 = Dscf::Credit::LoanProfile.find_or_create_by(
|
647
|
-
|
648
|
-
user: user2
|
755
|
+
loan_application: loan_application1
|
649
756
|
) do |profile|
|
650
|
-
profile.
|
651
|
-
profile.
|
652
|
-
profile.
|
653
|
-
profile.reviewed_by = bank_admin
|
654
|
-
profile.review_branch = cbe_head_office
|
655
|
-
profile.review_date = Time.current
|
656
|
-
# Note: backer will be set when facilitators are created via API
|
757
|
+
profile.code = "BB000001"
|
758
|
+
profile.score = 78.5
|
759
|
+
profile.total_limit = 100000.00
|
657
760
|
end
|
658
761
|
|
659
|
-
#
|
762
|
+
# Create approved review for loan_profile1
|
763
|
+
Dscf::Core::Review.find_or_create_by(
|
764
|
+
reviewable: loan_profile1,
|
765
|
+
reviewed_by: admin_user
|
766
|
+
) do |review|
|
767
|
+
review.status = 'approved'
|
768
|
+
review.reviewed_at = Time.current
|
769
|
+
end
|
770
|
+
|
771
|
+
# 12. Loan Profile Scoring Specs (depends on loan profiles)
|
660
772
|
puts "Seeding loan profile scoring specs..."
|
661
773
|
Dscf::Credit::LoanProfileScoringSpec.create!(
|
662
774
|
loan_profile: loan_profile1,
|
@@ -836,4 +948,5 @@ puts "- Payments: #{Dscf::Credit::Payment.count}"
|
|
836
948
|
puts "- Facilitators: #{Dscf::Credit::Facilitator.count} (will be created via API)"
|
837
949
|
puts "- System Configs: #{Dscf::Credit::SystemConfig.count}"
|
838
950
|
puts "- Scoring Parameters: #{Dscf::Credit::ScoringParameter.count}"
|
839
|
-
puts "-
|
951
|
+
puts "- Loan Applications: #{Dscf::Credit::LoanApplication.count}"
|
952
|
+
puts "- Facilitator Applications: #{Dscf::Credit::FacilitatorApplication.count}"
|