dscf-credit 0.4.46 → 0.4.48

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/dscf/credit/categories_controller.rb +6 -8
  3. data/app/controllers/dscf/credit/credit_limit_calculations_controller.rb +3 -3
  4. data/app/controllers/dscf/credit/credit_lines_controller.rb +7 -7
  5. data/app/controllers/dscf/credit/credit_products_controller.rb +66 -0
  6. data/app/controllers/dscf/credit/loan_applications_controller.rb +15 -15
  7. data/app/controllers/dscf/credit/loan_profiles_controller.rb +5 -5
  8. data/app/controllers/dscf/credit/scoring_tables_controller.rb +4 -4
  9. data/app/models/dscf/credit/category.rb +2 -6
  10. data/app/models/dscf/credit/credit_line.rb +13 -3
  11. data/app/models/dscf/credit/credit_product.rb +26 -0
  12. data/app/models/dscf/credit/loan_application.rb +2 -2
  13. data/app/models/dscf/credit/scoring_table.rb +2 -2
  14. data/app/serializers/dscf/credit/category_serializer.rb +1 -3
  15. data/app/serializers/dscf/credit/credit_line_serializer.rb +1 -1
  16. data/app/serializers/dscf/credit/credit_product_serializer.rb +13 -0
  17. data/app/serializers/dscf/credit/loan_application_serializer.rb +1 -1
  18. data/app/serializers/dscf/credit/scoring_table_serializer.rb +1 -1
  19. data/app/services/dscf/credit/credit_scoring_engine.rb +4 -4
  20. data/app/services/dscf/credit/facility_limit_calculation_engine.rb +10 -10
  21. data/app/services/dscf/credit/loan_profile_creation_service.rb +3 -3
  22. data/config/locales/en.yml +24 -0
  23. data/config/routes.rb +9 -0
  24. data/db/migrate/{20260219000003_create_dscf_credit_categories.rb → 20260219000030_create_dscf_credit_categories.rb} +0 -6
  25. data/db/migrate/20260219000040_create_dscf_credit_credit_products.rb +17 -0
  26. data/db/migrate/{20260219000005_create_dscf_credit_credit_lines.rb → 20260219000060_create_dscf_credit_credit_lines.rb} +1 -1
  27. data/db/migrate/{20260219000013_create_dscf_credit_loan_applications.rb → 20260219000140_create_dscf_credit_loan_applications.rb} +1 -1
  28. data/db/seeds.rb +40 -8
  29. data/lib/dscf/credit/version.rb +1 -1
  30. data/spec/factories/dscf/credit/categories.rb +0 -1
  31. data/spec/factories/dscf/credit/credit_lines.rb +6 -2
  32. data/spec/factories/dscf/credit/credit_products.rb +31 -0
  33. data/spec/factories/dscf/credit/loan_applications.rb +1 -1
  34. metadata +35 -31
  35. data/db/dev_seeds.rb +0 -1235
  36. /data/db/migrate/{20260219000001_create_dscf_credit_banks.rb → 20260219000010_create_dscf_credit_banks.rb} +0 -0
  37. /data/db/migrate/{20260219000002_create_dscf_credit_scoring_tables.rb → 20260219000020_create_dscf_credit_scoring_tables.rb} +0 -0
  38. /data/db/migrate/{20260219000004_create_dscf_credit_bank_branches.rb → 20260219000050_create_dscf_credit_bank_branches.rb} +0 -0
  39. /data/db/migrate/{20260219000006_create_dscf_credit_information_sources.rb → 20260219000070_create_dscf_credit_information_sources.rb} +0 -0
  40. /data/db/migrate/{20260219000007_create_dscf_credit_scoring_parameters.rb → 20260219000080_create_dscf_credit_scoring_parameters.rb} +0 -0
  41. /data/db/migrate/{20260219000008_create_dscf_credit_credit_line_specs.rb → 20260219000090_create_dscf_credit_credit_line_specs.rb} +0 -0
  42. /data/db/migrate/{20260219000009_create_dscf_credit_scoring_table_parameters.rb → 20260219000100_create_dscf_credit_scoring_table_parameters.rb} +0 -0
  43. /data/db/migrate/{20260219000010_create_dscf_credit_scoring_table_normalizers.rb → 20260219000110_create_dscf_credit_scoring_table_normalizers.rb} +0 -0
  44. /data/db/migrate/{20260219000011_create_dscf_credit_system_config_definitions.rb → 20260219000120_create_dscf_credit_system_config_definitions.rb} +0 -0
  45. /data/db/migrate/{20260219000012_create_dscf_credit_system_configs.rb → 20260219000130_create_dscf_credit_system_configs.rb} +0 -0
  46. /data/db/migrate/{20260219000014_create_dscf_credit_loan_profiles.rb → 20260219000150_create_dscf_credit_loan_profiles.rb} +0 -0
  47. /data/db/migrate/{20260219000015_create_dscf_credit_scoring_results.rb → 20260219000160_create_dscf_credit_scoring_results.rb} +0 -0
  48. /data/db/migrate/{20260219000016_create_dscf_credit_facilitator_applications.rb → 20260219000170_create_dscf_credit_facilitator_applications.rb} +0 -0
  49. /data/db/migrate/{20260219000017_create_dscf_credit_facilitators.rb → 20260219000180_create_dscf_credit_facilitators.rb} +0 -0
  50. /data/db/migrate/{20260219000018_create_dscf_credit_facilitator_performances.rb → 20260219000190_create_dscf_credit_facilitator_performances.rb} +0 -0
  51. /data/db/migrate/{20260219000019_create_dscf_credit_loans.rb → 20260219000200_create_dscf_credit_loans.rb} +0 -0
  52. /data/db/migrate/{20260219000020_create_dscf_credit_loan_transactions.rb → 20260219000210_create_dscf_credit_loan_transactions.rb} +0 -0
  53. /data/db/migrate/{20260219000021_create_dscf_credit_daily_routine_transactions.rb → 20260219000220_create_dscf_credit_daily_routine_transactions.rb} +0 -0
  54. /data/db/migrate/{20260219000022_create_dscf_credit_accounting_audit_requests.rb → 20260219000230_create_dscf_credit_accounting_audit_requests.rb} +0 -0
  55. /data/db/migrate/{20260219000023_create_dscf_credit_failed_operations_logs.rb → 20260219000240_create_dscf_credit_failed_operations_logs.rb} +0 -0
  56. /data/db/migrate/{20260219000024_create_dscf_credit_accounting_entries.rb → 20260219000250_create_dscf_credit_accounting_entries.rb} +0 -0
  57. /data/db/migrate/{20260219000025_create_dscf_credit_bank_staff.rb → 20260219000260_create_dscf_credit_bank_staff.rb} +0 -0
  58. /data/db/migrate/{20260219000026_create_dscf_credit_eligible_credit_lines.rb → 20260219000270_create_dscf_credit_eligible_credit_lines.rb} +0 -0
  59. /data/db/migrate/{20260219000027_create_dscf_credit_loan_accruals.rb → 20260219000280_create_dscf_credit_loan_accruals.rb} +0 -0
  60. /data/db/migrate/{20260219000028_create_dscf_credit_loan_application_data.rb → 20260219000290_create_dscf_credit_loan_application_data.rb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9f80c67743753180bfd10ef6eb0bc0306c52ee04eb452b3010a073e2ccd9057
4
- data.tar.gz: 123b03963cd6cc6b98395ed5d6172692e293b26194da7fb58d40ba8f5fc13753
3
+ metadata.gz: 202f7f16da67e4370a2e290955089d9872866d8c574d3e2a8fb61a980c2dcfff
4
+ data.tar.gz: 3ce121d8bc09a5dcc475aed9e4376a1558a83da30032ffe4f5534cf3ddc32ba6
5
5
  SHA512:
6
- metadata.gz: 83c4541282e5fb60ffb91ae403730a429e1cbceb72b0d500863582c142a551ce52eb59341b16c35b6e8842f15ff502975fe52fbd0c99a87958cfe8eae6da8612
7
- data.tar.gz: 0d2467ce32293e362a67ef9ece84127d17599157cf109d95e7bd6c21671188aaf52f3f85037464ab86f94512179cea8276ba0469e500feffea973d9f89828736
6
+ metadata.gz: daaec706ba7d573f78a42d81e9c25c794b3db39c1c68556fdd633c3a013604c5f034f689c2ff34a3f2f0d19c4b385d3da0a14c404f1942f55beed99736917653
7
+ data.tar.gz: 18dfaee9c7c9b25bcf9847f1c98004e1ec2bace0bbe987613913ff7db164c98cb8b6233e3db6736a1d1dcfb7d233b801a25a145828928fd6f2d3d65ab34741c4
@@ -10,26 +10,24 @@ module Dscf
10
10
  :bank_id,
11
11
  :category_type,
12
12
  :name,
13
- :description,
14
- :document_reference,
15
- :scoring_table_id
13
+ :description
16
14
  )
17
15
  end
18
16
 
19
17
  def eager_loaded_associations
20
- [ :bank, :scoring_table, :credit_lines, :scoring_parameters ]
18
+ [ :bank, :scoring_parameters ]
21
19
  end
22
20
 
23
21
  def allowed_order_columns
24
- %w[id category_type name description document_reference created_at updated_at]
22
+ %w[id category_type name description created_at updated_at]
25
23
  end
26
24
 
27
25
  def default_serializer_includes
28
26
  {
29
27
  index: [],
30
- show: [ :bank, :scoring_table, :credit_lines, :scoring_parameters ],
31
- create: [ :bank, :scoring_table ],
32
- update: [ :bank, :scoring_table, :credit_lines, :scoring_parameters ]
28
+ show: [ :bank, :scoring_parameters ],
29
+ create: [ :bank ],
30
+ update: [ :bank, :scoring_parameters ]
33
31
  }
34
32
  end
35
33
  end
@@ -2,9 +2,9 @@ module Dscf::Credit
2
2
  class CreditLimitCalculationsController < ApplicationController
3
3
  def create
4
4
  loan_profile = Dscf::Credit::LoanProfile.find(params[:loan_profile_id])
5
- category = Dscf::Credit::Category.find(params[:category_id])
5
+ credit_product = Dscf::Credit::CreditProduct.find(params[:credit_product_id])
6
6
 
7
- engine = Dscf::Credit::FacilityLimitCalculationEngine.new(loan_profile.id, category.id)
7
+ engine = Dscf::Credit::FacilityLimitCalculationEngine.new(loan_profile.id, credit_product.id)
8
8
  result = engine.calculate_facility_limits
9
9
 
10
10
  if result[:success]
@@ -13,7 +13,7 @@ module Dscf::Credit
13
13
  "credit_limit_calculation.success.create",
14
14
  data: {
15
15
  loan_profile: loan_profile,
16
- category: category,
16
+ credit_product: credit_product,
17
17
  eligible_credit_lines: result[:data],
18
18
  calculation_summary: {
19
19
  total_credit_lines_processed: result[:data]&.size || 0,
@@ -34,7 +34,7 @@ module Dscf::Credit
34
34
  def model_params
35
35
  params.require(:credit_line).permit(
36
36
  :bank_id,
37
- :category_id,
37
+ :credit_product_id,
38
38
  :name,
39
39
  :code,
40
40
  :description,
@@ -44,7 +44,7 @@ module Dscf::Credit
44
44
 
45
45
  def eager_loaded_associations
46
46
  [
47
- :bank, :category, :created_by, :loans, :eligible_credit_lines,
47
+ :bank, :credit_product, :created_by, :loans, :eligible_credit_lines,
48
48
  credit_line_specs: :base_scoring_parameter,
49
49
  reviews: { reviewed_by: :user_profile },
50
50
  audit_logs: :actor
@@ -52,21 +52,21 @@ module Dscf::Credit
52
52
  end
53
53
 
54
54
  def allowed_order_columns
55
- %w[id name code created_at updated_at category_id]
55
+ %w[id name code created_at updated_at credit_product_id]
56
56
  end
57
57
 
58
58
  def default_serializer_includes
59
59
  {
60
- index: [ :bank, :category, reviews: { reviewed_by: :user_profile } ],
60
+ index: [ :bank, :credit_product, reviews: { reviewed_by: :user_profile } ],
61
61
  show: [
62
- :bank, :category, :created_by, :loans, :eligible_credit_lines,
62
+ :bank, :credit_product, :created_by, :loans, :eligible_credit_lines,
63
63
  credit_line_specs: :base_scoring_parameter,
64
64
  reviews: { reviewed_by: :user_profile },
65
65
  audit_logs: :actor
66
66
  ],
67
- create: [ :bank, :category, :created_by, :reviews ],
67
+ create: [ :bank, :credit_product, :created_by, :reviews ],
68
68
  update: [
69
- :bank, :category, :created_by, :credit_line_specs, :loans, :eligible_credit_lines,
69
+ :bank, :credit_product, :created_by, :credit_line_specs, :loans, :eligible_credit_lines,
70
70
  reviews: { reviewed_by: :user_profile }
71
71
  ]
72
72
  }
@@ -0,0 +1,66 @@
1
+ module Dscf
2
+ module Credit
3
+ class CreditProductsController < ApplicationController
4
+ include Dscf::Core::Common
5
+ include Dscf::Core::ReviewableController
6
+ include Dscf::Core::AuditableController
7
+
8
+ auditable associated: [ :reviews ],
9
+ on: %i[approve submit reject request_modification resubmit]
10
+
11
+ auditable on: %i[create],
12
+ associated: { reviews: { only: [ :status ] } }
13
+
14
+ def create
15
+ super do
16
+ credit_product = @clazz.new(model_params)
17
+ credit_product.reviews.build(status: "draft", context: "default")
18
+ credit_product
19
+ end
20
+ end
21
+
22
+ def update
23
+ unless @obj.editable?
24
+ return render_error(
25
+ errors: [ "Cannot update credit product after submission. Use modification request workflow instead." ],
26
+ status: :unprocessable_entity
27
+ )
28
+ end
29
+ super
30
+ end
31
+
32
+ private
33
+
34
+ def model_params
35
+ params.require(:credit_product).permit(
36
+ :bank_id,
37
+ :scoring_table_id,
38
+ :name,
39
+ :description,
40
+ :document_reference
41
+ )
42
+ end
43
+
44
+ def eager_loaded_associations
45
+ [
46
+ :bank, :scoring_table, :credit_lines,
47
+ reviews: { reviewed_by: :user_profile },
48
+ audit_logs: :actor
49
+ ]
50
+ end
51
+
52
+ def allowed_order_columns
53
+ %w[id name description created_at updated_at bank_id]
54
+ end
55
+
56
+ def default_serializer_includes
57
+ {
58
+ index: [ :bank, reviews: { reviewed_by: :user_profile } ],
59
+ show: [ :bank, :scoring_table, :credit_lines, reviews: { reviewed_by: :user_profile }, audit_logs: :actor ],
60
+ create: [ :bank, :reviews ],
61
+ update: [ :bank, :scoring_table, reviews: { reviewed_by: :user_profile }, audit_logs: :actor ]
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -32,7 +32,7 @@ module Dscf::Credit
32
32
  end
33
33
 
34
34
  scoring_result_data = {
35
- scoring_table_id: loan_application.category&.scoring_table&.id,
35
+ scoring_table_id: loan_application.credit_product&.scoring_table&.id,
36
36
  scoring_input_data: input_snapshot,
37
37
  breakdown: {} # Breakdown unavailable for manually-approved pending applications
38
38
  }
@@ -100,11 +100,11 @@ module Dscf::Credit
100
100
  return render_error(errors: [ "Information source '#{source_code}' not found" ], status: :not_found)
101
101
  end
102
102
 
103
- category = @obj.category
104
- scoring_table = category&.scoring_table
103
+ credit_product = @obj.credit_product
104
+ scoring_table = credit_product&.scoring_table
105
105
 
106
106
  unless scoring_table
107
- return render_error(errors: [ "No scoring table configured for this loan application's category" ], status: :unprocessable_entity)
107
+ return render_error(errors: [ "No scoring table configured for this loan application's credit product" ], status: :unprocessable_entity)
108
108
  end
109
109
 
110
110
  # Load parameters for this source with normalizers
@@ -156,7 +156,7 @@ module Dscf::Credit
156
156
 
157
157
  if result[:success]
158
158
  scoring_result_data = {
159
- scoring_table_id: loan_application.category&.scoring_table&.id,
159
+ scoring_table_id: loan_application.credit_product&.scoring_table&.id,
160
160
  breakdown: result[:breakdown],
161
161
  scoring_input_data: build_scoring_input_snapshot(loan_application)
162
162
  }
@@ -249,7 +249,7 @@ module Dscf::Credit
249
249
 
250
250
  # Build feedback message based on status and score
251
251
  def build_review_feedback(status, score, loan_application = nil)
252
- scoring_table = loan_application&.category&.scoring_table || @obj&.category&.scoring_table
252
+ scoring_table = loan_application&.credit_product&.scoring_table || @obj&.credit_product&.scoring_table
253
253
  passing = scoring_table&.passing_score || 60.0
254
254
  pending_thresh = scoring_table&.pending_threshold || 50.0
255
255
 
@@ -275,13 +275,13 @@ module Dscf::Credit
275
275
  end
276
276
 
277
277
  def build_eligibility_response(loan_application)
278
- category = loan_application.category
279
- return [] unless category
278
+ credit_product = loan_application.credit_product
279
+ return [] unless credit_product
280
280
 
281
281
  score = loan_application.score.to_f
282
282
  loan_profile = loan_application.loan_profile
283
283
 
284
- category.credit_lines.includes(credit_line_specs: :base_scoring_parameter).map do |credit_line|
284
+ credit_product.credit_lines.includes(credit_line_specs: :base_scoring_parameter).map do |credit_line|
285
285
  spec = credit_line.credit_line_specs.active.order(created_at: :desc).first
286
286
  next unless spec
287
287
 
@@ -326,7 +326,7 @@ module Dscf::Credit
326
326
  def model_params
327
327
  params.require(:loan_application).permit(
328
328
  :bank_id,
329
- :category_id,
329
+ :credit_product_id,
330
330
  :backer_type,
331
331
  :backer_id,
332
332
  :review_branch_id,
@@ -337,7 +337,7 @@ module Dscf::Credit
337
337
 
338
338
  def eager_loaded_associations
339
339
  [
340
- :bank, :user, :backer, :review_branch, :loan_profile, :category,
340
+ :bank, :user, :backer, :review_branch, :loan_profile, :credit_product,
341
341
  loan_application_data: [ :information_source ],
342
342
  reviews: { reviewed_by: :user_profile },
343
343
  audit_logs: :actor
@@ -351,22 +351,22 @@ module Dscf::Credit
351
351
  def default_serializer_includes
352
352
  {
353
353
  index: [
354
- :bank, :user, :backer, :review_branch, :loan_profile, :category,
354
+ :bank, :user, :backer, :review_branch, :loan_profile, :credit_product,
355
355
  loan_application_data: [ :information_source ],
356
356
  reviews: { reviewed_by: :user_profile }
357
357
  ],
358
358
  show: [
359
- :bank, :user, :backer, :review_branch, :loan_profile, :category,
359
+ :bank, :user, :backer, :review_branch, :loan_profile, :credit_product,
360
360
  loan_application_data: [ :information_source ],
361
361
  reviews: { reviewed_by: :user_profile },
362
362
  audit_logs: :actor
363
363
  ],
364
364
  create: [
365
- :bank, :user, :backer, :review_branch, :loan_profile, :category, :reviews,
365
+ :bank, :user, :backer, :review_branch, :loan_profile, :credit_product, :reviews,
366
366
  { loan_application_data: [ :information_source ] }
367
367
  ],
368
368
  update: [
369
- :bank, :user, :backer, :review_branch, :loan_profile, :category,
369
+ :bank, :user, :backer, :review_branch, :loan_profile, :credit_product,
370
370
  loan_application_data: [ :information_source ],
371
371
  reviews: { reviewed_by: :user_profile }
372
372
  ]
@@ -27,15 +27,15 @@ module Dscf::Credit
27
27
 
28
28
  def calculate_facility_limits
29
29
  loan_profile = @clazz.find(params[:id])
30
- category_id = facility_params[:category_id]
30
+ credit_product_id = facility_params[:credit_product_id]
31
31
 
32
32
  return render_error(
33
33
  "loan_profile.errors.calculate_facility_limits",
34
- errors: [ "Category ID is required" ],
34
+ errors: [ "Credit Product ID is required" ],
35
35
  status: :unprocessable_entity
36
- ) unless category_id
36
+ ) unless credit_product_id
37
37
 
38
- facility_engine = FacilityLimitCalculationEngine.new(loan_profile.id, category_id)
38
+ facility_engine = FacilityLimitCalculationEngine.new(loan_profile.id, credit_product_id)
39
39
  result = facility_engine.calculate_facility_limits
40
40
 
41
41
  if result[:success]
@@ -110,7 +110,7 @@ module Dscf::Credit
110
110
  end
111
111
 
112
112
  def facility_params
113
- params.permit(:category_id)
113
+ params.permit(:credit_product_id)
114
114
  end
115
115
 
116
116
  def eager_loaded_associations
@@ -69,7 +69,7 @@ module Dscf::Credit
69
69
 
70
70
  def eager_loaded_associations
71
71
  [
72
- :bank, :created_by, :parent_template, :scoring_table_parameters, :categories,
72
+ :bank, :created_by, :parent_template, :scoring_table_parameters, :credit_products,
73
73
  reviews: { reviewed_by: :user_profile },
74
74
  audit_logs: :actor
75
75
  ]
@@ -81,15 +81,15 @@ module Dscf::Credit
81
81
 
82
82
  def default_serializer_includes
83
83
  {
84
- index: [ :bank, :categories, reviews: { reviewed_by: :user_profile } ],
84
+ index: [ :bank, :credit_products, reviews: { reviewed_by: :user_profile } ],
85
85
  show: [
86
- :bank, :created_by, :parent_template, :scoring_table_parameters, :categories,
86
+ :bank, :created_by, :parent_template, :scoring_table_parameters, :credit_products,
87
87
  reviews: { reviewed_by: :user_profile },
88
88
  audit_logs: :actor
89
89
  ],
90
90
  create: [ :bank, :created_by, :reviews ],
91
91
  update: [
92
- :bank, :created_by, :categories,
92
+ :bank, :created_by, :credit_products,
93
93
  reviews: { reviewed_by: :user_profile }
94
94
  ]
95
95
  }
@@ -4,10 +4,6 @@ module Dscf
4
4
  self.table_name = "dscf_credit_categories"
5
5
 
6
6
  belongs_to :bank, class_name: "Dscf::Credit::Bank", optional: true
7
- belongs_to :scoring_table, class_name: "Dscf::Credit::ScoringTable",
8
- foreign_key: "scoring_table_id", optional: true
9
- has_many :credit_lines, class_name: "Dscf::Credit::CreditLine",
10
- foreign_key: "category_id", dependent: :nullify
11
7
  has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter",
12
8
  foreign_key: "category_id", dependent: :nullify
13
9
 
@@ -18,11 +14,11 @@ module Dscf
18
14
  scope :by_bank, ->(bank_id) { where(bank_id: bank_id) }
19
15
 
20
16
  def self.ransackable_attributes(auth_object = nil)
21
- %w[id category_type name description document_reference bank_id created_at updated_at]
17
+ %w[id category_type name description bank_id created_at updated_at]
22
18
  end
23
19
 
24
20
  def self.ransackable_associations(auth_object = nil)
25
- %w[bank credit_lines scoring_table scoring_parameters]
21
+ %w[bank scoring_parameters]
26
22
  end
27
23
  end
28
24
  end
@@ -6,23 +6,33 @@ module Dscf::Credit
6
6
  include Dscf::Core::AuditableModel
7
7
 
8
8
  belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
9
- belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
9
+ belongs_to :credit_product, class_name: "Dscf::Credit::CreditProduct", foreign_key: "credit_product_id"
10
10
  belongs_to :created_by, polymorphic: true
11
11
 
12
12
  has_many :credit_line_specs, class_name: "Dscf::Credit::CreditLineSpec", foreign_key: "credit_line_id", dependent: :destroy
13
13
  has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "credit_line_id", dependent: :destroy
14
14
  has_many :eligible_credit_lines, class_name: "Dscf::Credit::EligibleCreditLine", foreign_key: "credit_line_id", dependent: :destroy
15
- has_many :scoring_parameters, through: :category, source: :scoring_parameters
16
15
 
17
16
  validates :name, presence: true
18
17
  validates :code, uniqueness: { scope: :bank_id }, allow_blank: true
18
+ validate :credit_product_must_be_approved, if: -> { credit_product_id_changed? || new_record? }
19
19
 
20
20
  def self.ransackable_attributes(auth_object = nil)
21
21
  %w[id name code description document_reference created_at updated_at]
22
22
  end
23
23
 
24
24
  def self.ransackable_associations(auth_object = nil)
25
- %w[bank category created_by credit_line_specs loans eligible_credit_lines scoring_parameters reviews]
25
+ %w[bank credit_product created_by credit_line_specs loans eligible_credit_lines reviews]
26
+ end
27
+
28
+ private
29
+
30
+ def credit_product_must_be_approved
31
+ return unless credit_product
32
+
33
+ unless credit_product.approved?
34
+ errors.add(:credit_product, "must be approved before creating a credit line")
35
+ end
26
36
  end
27
37
  end
28
38
  end
@@ -0,0 +1,26 @@
1
+ module Dscf
2
+ module Credit
3
+ class CreditProduct < ApplicationRecord
4
+ self.table_name = "dscf_credit_credit_products"
5
+
6
+ include Dscf::Core::ReviewableModel
7
+ include Dscf::Core::AuditableModel
8
+
9
+ belongs_to :bank, class_name: "Dscf::Credit::Bank"
10
+ belongs_to :scoring_table, class_name: "Dscf::Credit::ScoringTable", optional: true
11
+ has_many :credit_lines, class_name: "Dscf::Credit::CreditLine",
12
+ foreign_key: :credit_product_id, dependent: :nullify
13
+
14
+ validates :name, presence: true, uniqueness: { scope: :bank_id }
15
+ validates :bank, presence: true
16
+
17
+ def self.ransackable_attributes(auth_object = nil)
18
+ %w[id name description document_reference bank_id scoring_table_id created_at updated_at]
19
+ end
20
+
21
+ def self.ransackable_associations(auth_object = nil)
22
+ %w[bank scoring_table credit_lines reviews audit_logs]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -11,7 +11,7 @@ module Dscf::Credit
11
11
  end
12
12
  belongs_to :backer, polymorphic: true
13
13
  belongs_to :review_branch, class_name: "Dscf::Credit::BankBranch", foreign_key: "review_branch_id"
14
- belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id", optional: true
14
+ belongs_to :credit_product, class_name: "Dscf::Credit::CreditProduct", foreign_key: "credit_product_id", optional: true
15
15
 
16
16
  has_one :loan_profile, class_name: "Dscf::Credit::LoanProfile", foreign_key: "loan_application_id", dependent: :destroy
17
17
  has_many :loan_application_data, class_name: "Dscf::Credit::LoanApplicationDatum", foreign_key: "loan_application_id", dependent: :destroy
@@ -26,7 +26,7 @@ module Dscf::Credit
26
26
  end
27
27
 
28
28
  def self.ransackable_associations(auth_object = nil)
29
- %w[bank user backer review_branch category loan_profile loan_application_data reviews audit_logs]
29
+ %w[bank user backer review_branch credit_product loan_profile loan_application_data reviews audit_logs]
30
30
  end
31
31
  end
32
32
  end
@@ -11,7 +11,7 @@ module Dscf::Credit
11
11
  has_many :scoring_table_parameters, class_name: "Dscf::Credit::ScoringTableParameter", foreign_key: "scoring_table_id", dependent: :destroy
12
12
  has_many :scoring_parameters, through: :scoring_table_parameters
13
13
  has_many :scoring_results, class_name: "Dscf::Credit::ScoringResult", foreign_key: "scoring_table_id"
14
- has_many :categories, class_name: "Dscf::Credit::Category", foreign_key: "scoring_table_id"
14
+ has_many :credit_products, class_name: "Dscf::Credit::CreditProduct", foreign_key: "scoring_table_id"
15
15
 
16
16
  validates :code, presence: true, uniqueness: true
17
17
  validates :name, presence: true, uniqueness: { scope: :bank_id }
@@ -28,7 +28,7 @@ module Dscf::Credit
28
28
  end
29
29
 
30
30
  def self.ransackable_associations(auth_object = nil)
31
- %w[bank created_by parent_template scoring_table_parameters scoring_parameters scoring_results categories reviews audit_logs]
31
+ %w[bank created_by parent_template scoring_table_parameters scoring_parameters scoring_results credit_products reviews audit_logs]
32
32
  end
33
33
 
34
34
  private
@@ -1,11 +1,9 @@
1
1
  module Dscf
2
2
  module Credit
3
3
  class CategorySerializer < ActiveModel::Serializer
4
- attributes :id, :category_type, :name, :description, :document_reference, :created_at, :updated_at
4
+ attributes :id, :category_type, :name, :description, :created_at, :updated_at
5
5
 
6
6
  belongs_to :bank, serializer: Dscf::Credit::BankSerializer
7
- belongs_to :scoring_table, serializer: Dscf::Credit::ScoringTableSerializer
8
- has_many :credit_lines, serializer: Dscf::Credit::CreditLineSerializer
9
7
  has_many :scoring_parameters, serializer: Dscf::Credit::ScoringParameterSerializer
10
8
  end
11
9
  end
@@ -4,7 +4,7 @@ module Dscf::Credit
4
4
  :created_at, :updated_at
5
5
 
6
6
  belongs_to :bank, serializer: Dscf::Credit::BankSerializer
7
- belongs_to :category, serializer: Dscf::Credit::CategorySerializer
7
+ belongs_to :credit_product, serializer: Dscf::Credit::CreditProductSerializer
8
8
  belongs_to :created_by, serializer: Dscf::Core::UserSerializer
9
9
  has_many :credit_line_specs, serializer: Dscf::Credit::CreditLineSpecSerializer
10
10
  has_many :loans, serializer: Dscf::Credit::LoanSerializer
@@ -0,0 +1,13 @@
1
+ module Dscf
2
+ module Credit
3
+ class CreditProductSerializer < ActiveModel::Serializer
4
+ attributes :id, :name, :description, :document_reference, :created_at, :updated_at
5
+
6
+ belongs_to :bank, serializer: Dscf::Credit::BankSerializer
7
+ belongs_to :scoring_table, serializer: Dscf::Credit::ScoringTableSerializer
8
+ has_many :credit_lines, serializer: Dscf::Credit::CreditLineSerializer
9
+ has_many :reviews, serializer: Dscf::Core::ReviewSerializer
10
+ has_many :audit_logs, serializer: Dscf::Core::AuditLogSerializer
11
+ end
12
+ end
13
+ end
@@ -6,7 +6,7 @@ module Dscf::Credit
6
6
  belongs_to :user, serializer: Dscf::Core::UserSerializer
7
7
  belongs_to :backer, polymorphic: true
8
8
  belongs_to :review_branch, serializer: Dscf::Credit::BankBranchSerializer
9
- belongs_to :category, serializer: Dscf::Credit::CategorySerializer
9
+ belongs_to :credit_product, serializer: Dscf::Credit::CreditProductSerializer
10
10
  has_many :reviews, serializer: Dscf::Core::ReviewSerializer
11
11
  has_many :audit_logs, serializer: Dscf::Core::AuditLogSerializer
12
12
  has_many :loan_application_data, serializer: Dscf::Credit::LoanApplicationDatumSerializer
@@ -7,7 +7,7 @@ module Dscf::Credit
7
7
  belongs_to :bank, serializer: Dscf::Credit::BankSerializer
8
8
  belongs_to :created_by, polymorphic: true
9
9
  belongs_to :parent_template, serializer: Dscf::Credit::ScoringTableSerializer
10
- has_many :categories, serializer: Dscf::Credit::CategorySerializer
10
+ has_many :credit_products, serializer: Dscf::Credit::CreditProductSerializer
11
11
  has_many :scoring_table_parameters
12
12
  has_many :reviews, serializer: Dscf::Core::ReviewSerializer
13
13
  has_many :audit_logs, serializer: Dscf::Core::AuditLogSerializer
@@ -2,14 +2,14 @@ module Dscf::Credit
2
2
  class CreditScoringEngine
3
3
  def initialize(loan_application)
4
4
  @loan_application = loan_application
5
- @category = loan_application.category
6
- @scoring_table = @category&.scoring_table
5
+ @credit_product = loan_application.credit_product
6
+ @scoring_table = @credit_product&.scoring_table
7
7
  @data_by_source_id = load_data_by_source
8
8
  end
9
9
 
10
10
  def calculate_score
11
- return failure("No category assigned to loan application") unless @category
12
- return failure("No scoring table configured for category '#{@category.name}'") unless @scoring_table
11
+ return failure("No credit product assigned to loan application") unless @credit_product
12
+ return failure("No scoring table configured for credit product '#{@credit_product.name}'") unless @scoring_table
13
13
 
14
14
  parameters = @scoring_table.scoring_table_parameters
15
15
  .includes(:scoring_parameter, :scoring_table_normalizers, :information_source)
@@ -1,18 +1,18 @@
1
1
  module Dscf::Credit
2
2
  class FacilityLimitCalculationEngine
3
- attr_reader :loan_profile, :category_id, :errors
3
+ attr_reader :loan_profile, :credit_product_id, :errors
4
4
 
5
- def initialize(loan_profile_id, category_id)
5
+ def initialize(loan_profile_id, credit_product_id)
6
6
  @errors = []
7
7
  @loan_profile = LoanProfile.find(loan_profile_id)
8
- @category_id = category_id
8
+ @credit_product_id = credit_product_id
9
9
  rescue ActiveRecord::RecordNotFound => e
10
10
  @errors << "Loan profile not found: \#{e.message}"
11
11
  end
12
12
 
13
13
  def calculate_facility_limits
14
14
  return error_result("Loan profile is required") unless loan_profile
15
- return error_result("Category ID is required") unless category_id
15
+ return error_result("Credit Product ID is required") unless credit_product_id
16
16
 
17
17
  begin
18
18
  ActiveRecord::Base.transaction do
@@ -22,7 +22,7 @@ module Dscf::Credit
22
22
 
23
23
  credit_lines = get_credit_lines_for_calculation
24
24
  if credit_lines.empty?
25
- return error_result("No credit lines found for category \#{category_id} and bank \#{loan_profile.loan_application.bank_id}")
25
+ return error_result("No credit lines found for credit product #{credit_product_id} and bank #{loan_profile.loan_application.bank_id}")
26
26
  end
27
27
 
28
28
  eligible_credit_lines = []
@@ -67,9 +67,9 @@ module Dscf::Credit
67
67
  private
68
68
 
69
69
  def get_credit_lines_for_calculation
70
- CreditLine.joins(:category, :credit_line_specs)
70
+ CreditLine.joins(:credit_product, :credit_line_specs)
71
71
  .where(
72
- category_id: category_id,
72
+ credit_product_id: credit_product_id,
73
73
  bank_id: loan_profile.loan_application.bank_id,
74
74
  dscf_credit_credit_line_specs: { active: true }
75
75
  )
@@ -161,9 +161,9 @@ module Dscf::Credit
161
161
  end
162
162
 
163
163
  def get_scoring_table
164
- category = Category.find_by(id: category_id)
165
- return nil unless category&.scoring_table_id
166
- ScoringTable.find_by(id: category.scoring_table_id)
164
+ credit_product = CreditProduct.find_by(id: credit_product_id)
165
+ return nil unless credit_product&.scoring_table_id
166
+ ScoringTable.find_by(id: credit_product.scoring_table_id)
167
167
  end
168
168
 
169
169
  def update_loan_profile_total_limit
@@ -82,10 +82,10 @@ module Dscf::Credit
82
82
  end
83
83
 
84
84
  def calculate_facility_limits(loan_profile)
85
- category = @loan_application.category
86
- return unless category
85
+ credit_product = @loan_application.credit_product
86
+ return unless credit_product
87
87
 
88
- engine = FacilityLimitCalculationEngine.new(loan_profile.id, category.id)
88
+ engine = FacilityLimitCalculationEngine.new(loan_profile.id, credit_product.id)
89
89
  result = engine.calculate_facility_limits
90
90
 
91
91
  unless result[:success]
@@ -179,6 +179,30 @@ en:
179
179
  update: "Failed to update credit line specification"
180
180
  destroy: "Failed to delete credit line specification"
181
181
 
182
+ credit_product:
183
+ success:
184
+ index: "Credit products retrieved successfully"
185
+ show: "Credit product details retrieved successfully"
186
+ create: "Credit product created successfully"
187
+ update: "Credit product updated successfully"
188
+ submit: "Credit product submitted for review successfully"
189
+ approve: "Credit product approved successfully"
190
+ reject: "Credit product rejected successfully"
191
+ destroy: "Credit product deleted successfully"
192
+ request_modification: "Modification requested for credit product successfully"
193
+ resubmit: "Credit product resubmitted successfully"
194
+ errors:
195
+ index: "Failed to retrieve credit products"
196
+ show: "Failed to retrieve credit product details"
197
+ create: "Failed to create credit product"
198
+ update: "Failed to update credit product"
199
+ submit: "Failed to submit credit product for review"
200
+ approve: "Failed to approve credit product"
201
+ reject: "Failed to reject credit product"
202
+ destroy: "Failed to delete credit product"
203
+ request_modification: "Failed to request modification for credit product"
204
+ resubmit: "Failed to resubmit credit product"
205
+
182
206
  credit_line:
183
207
  success:
184
208
  index: "Credit lines retrieved successfully"