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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/dscf/core/copilot-instructions.md +683 -0
  3. data/app/controllers/concerns/dscf/core/reviewable_controller.rb +347 -0
  4. data/app/controllers/dscf/credit/categories_controller.rb +3 -3
  5. data/app/controllers/dscf/credit/credit_lines_controller.rb +21 -13
  6. data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +50 -8
  7. data/app/controllers/dscf/credit/facilitator_applications_controller.rb +35 -0
  8. data/app/controllers/dscf/credit/facilitators_controller.rb +8 -96
  9. data/app/controllers/dscf/credit/loan_applications_controller.rb +252 -0
  10. data/app/controllers/dscf/credit/loan_profiles_controller.rb +61 -68
  11. data/app/controllers/dscf/credit/payment_requests_controller.rb +3 -5
  12. data/app/controllers/dscf/credit/scoring_parameters_controller.rb +59 -13
  13. data/app/controllers/dscf/credit/system_configs_controller.rb +30 -12
  14. data/app/models/concerns/core/reviewable_model.rb +31 -0
  15. data/app/models/dscf/credit/bank.rb +3 -3
  16. data/app/models/dscf/credit/bank_branch.rb +1 -1
  17. data/app/models/dscf/credit/category.rb +1 -2
  18. data/app/models/dscf/credit/credit_line.rb +4 -10
  19. data/app/models/dscf/credit/eligible_credit_line.rb +2 -2
  20. data/app/models/dscf/credit/facilitator.rb +6 -17
  21. data/app/models/dscf/credit/facilitator_application.rb +20 -0
  22. data/app/models/dscf/credit/loan_application.rb +30 -0
  23. data/app/models/dscf/credit/loan_profile.rb +10 -30
  24. data/app/models/dscf/credit/parameter_normalizer.rb +1 -1
  25. data/app/models/dscf/credit/scoring_parameter.rb +5 -7
  26. data/app/models/dscf/credit/system_config.rb +4 -9
  27. data/app/serializers/dscf/credit/category_serializer.rb +0 -1
  28. data/app/serializers/dscf/credit/credit_line_serializer.rb +2 -2
  29. data/app/serializers/dscf/credit/facilitator_application_serializer.rb +7 -0
  30. data/app/serializers/dscf/credit/facilitator_serializer.rb +3 -6
  31. data/app/serializers/dscf/credit/loan_application_serializer.rb +12 -0
  32. data/app/serializers/dscf/credit/loan_profile_serializer.rb +3 -6
  33. data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +3 -4
  34. data/app/serializers/dscf/credit/system_config_serializer.rb +2 -2
  35. data/app/services/dscf/credit/credit_scoring_engine.rb +258 -0
  36. data/app/services/dscf/credit/facility_limit_calculation_engine.rb +159 -0
  37. data/app/services/dscf/credit/loan_profile_creation_service.rb +91 -0
  38. data/app/services/dscf/credit/risk_application_service.rb +61 -11
  39. data/config/locales/en.yml +63 -48
  40. data/config/routes.rb +31 -17
  41. data/db/migrate/20250822091131_create_dscf_credit_credit_lines.rb +1 -8
  42. data/db/migrate/20250822091820_create_dscf_credit_system_configs.rb +0 -7
  43. data/db/migrate/20250822092050_create_dscf_credit_scoring_parameters.rb +2 -6
  44. data/db/migrate/20250822092225_create_dscf_credit_parameter_normalizers.rb +1 -1
  45. data/db/migrate/20250822092236_create_dscf_credit_loan_applications.rb +20 -0
  46. data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +7 -19
  47. data/db/migrate/20250822092426_create_dscf_credit_facilitator_applications.rb +10 -0
  48. data/db/migrate/20250822092436_create_dscf_credit_facilitators.rb +1 -16
  49. data/db/seeds.rb +316 -203
  50. data/lib/dscf/credit/version.rb +1 -1
  51. data/spec/factories/dscf/credit/banks.rb +1 -1
  52. data/spec/factories/dscf/credit/credit_lines.rb +0 -23
  53. data/spec/factories/dscf/credit/facilitator_applications.rb +37 -0
  54. data/spec/factories/dscf/credit/facilitators.rb +8 -30
  55. data/spec/factories/dscf/credit/loan_applications.rb +42 -0
  56. data/spec/factories/dscf/credit/loan_profiles.rb +20 -34
  57. data/spec/factories/dscf/credit/parameter_normalizers.rb +4 -4
  58. data/spec/factories/dscf/credit/scoring_parameters.rb +14 -11
  59. data/spec/factories/dscf/credit/system_configs.rb +21 -5
  60. metadata +20 -10
  61. data/app/controllers/concerns/dscf/credit/reviewable.rb +0 -112
  62. data/app/controllers/dscf/credit/scoring_tables_controller.rb +0 -63
  63. data/app/models/dscf/credit/scoring_table.rb +0 -24
  64. data/app/serializers/dscf/credit/scoring_table_serializer.rb +0 -9
  65. data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +0 -18
  66. 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
- bank1 = Dscf::Credit::Bank.find_or_create_by(registration_number: 'BNK001') do |bank|
150
- bank.name = 'Commercial Bank of Ethiopia'
151
- bank.swift_code = 'CBETETAA'
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@cbe.com.et'
155
+ bank.contact_email = 'info@bunnabank.com'
156
156
  bank.contact_phone = '+251115510000'
157
157
  bank.status = 'active'
158
158
  end
159
159
 
160
- bank2 = Dscf::Credit::Bank.find_or_create_by(registration_number: 'BNK002') do |bank|
161
- bank.name = 'Awash Bank'
162
- bank.swift_code = 'AWSHETAA'
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
- cbe_head_office = Dscf::Credit::BankBranch.find_or_create_by(bank: bank1, branch_name: 'Head Office') do |branch|
174
- branch.branch_code = 'CBE-HO-001'
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@cbe.com.et'
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: bank1, branch_name: 'Merkato Branch') do |branch|
184
- branch.branch_code = 'CBE-MER-002'
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@cbe.com.et'
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: bank2, branch_name: 'Main Branch') do |branch|
194
- branch.branch_code = 'AWB-MN-001'
195
- branch.branch_address = 'Ras Desta Damtew Avenue, Addis Ababa'
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 = 'main@awashbank.com'
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
- cbe_main_branch = Dscf::Credit::BankBranch.find_by(bank: bank1, branch_name: 'Main Branch')
208
- cbe_merkato_branch = Dscf::Credit::BankBranch.find_by(bank: bank1, branch_name: 'Merkato Branch')
209
- awash_main_branch = Dscf::Credit::BankBranch.find_by(bank: bank2, branch_name: 'Main Branch')
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
- # CBE Main Branch Staff
216
- if cbe_main_branch && users.first
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: cbe_main_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 cbe_main_branch && users.second
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: cbe_main_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
- # CBE Merkato Branch Staff
235
- if cbe_merkato_branch && users.third
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: cbe_merkato_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 cbe_merkato_branch && users.fourth
237
+ if bunna_merkato_branch && users.fourth
245
238
  Dscf::Credit::BankStaff.find_or_create_by(
246
239
  user: users.fourth,
247
- bank_branch: cbe_merkato_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
- # Awash Bank Main Branch Staff
254
- if awash_main_branch && users.fifth
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: awash_main_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 awash_main_branch && users[5]
256
+ if bunna_bole_branch && users[5]
264
257
  Dscf::Credit::BankStaff.find_or_create_by(
265
258
  user: users[5],
266
- bank_branch: awash_main_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: bank1,
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: bank1,
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: bank2,
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
- Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def2) do |config|
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
- Dscf::Credit::SystemConfig.find_or_create_by(config_definition: config_def3) do |config|
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: bank1, name: 'SME Credit Line') do |line|
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 = 'CBE-SME-001'
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: bank1, name: 'Personal Credit Line') do |line|
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 = 'CBE-PER-002'
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: bank2, name: 'Agricultural Credit Line') do |line|
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 = 'AWB-AGR-001'
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 (depends on banks)
451
+ # 7. Scoring Parameters
447
452
  puts "Seeding scoring parameters..."
448
453
  scoring_param1 = Dscf::Credit::ScoringParameter.find_or_create_by(
449
- bank: bank1,
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: bank1,
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: bank1,
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: bank1, name: 'Employment Type')
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
- # 8.5. Scoring Tables (depends on credit lines and scoring parameters)
536
- puts "Seeding scoring tables..."
537
- # Get references to scoring parameters
538
- monthly_income_param = Dscf::Credit::ScoringParameter.find_by(bank: bank1, name: 'Monthly Income')
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
- # 9. Loan Profiles (depends on banks and users)
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
- bank: bank1,
648
- user: user2
755
+ loan_application: loan_application1
649
756
  ) do |profile|
650
- profile.status = 'approved'
651
- profile.total_amount = 100000.00
652
- profile.available_amount = 75000.00
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
- # 10. Loan Profile Scoring Specs (depends on loan profiles)
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 "- Scoring Tables: #{Dscf::Credit::ScoringTable.count}"
951
+ puts "- Loan Applications: #{Dscf::Credit::LoanApplication.count}"
952
+ puts "- Facilitator Applications: #{Dscf::Credit::FacilitatorApplication.count}"