dscf-credit 0.2.3 → 0.2.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/dscf/credit/categories_controller.rb +1 -1
- data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +3 -2
- data/app/controllers/dscf/credit/loan_applications_controller.rb +19 -17
- data/app/models/dscf/credit/category.rb +4 -5
- data/app/models/dscf/credit/eligible_credit_line.rb +3 -1
- data/app/serializers/dscf/credit/category_serializer.rb +1 -1
- data/app/serializers/dscf/credit/eligible_credit_line_serializer.rb +1 -1
- data/db/migrate/20250822091011_create_dscf_credit_categories.rb +3 -3
- data/db/migrate/20250917120000_create_dscf_credit_eligible_credit_lines.rb +1 -0
- data/db/seeds.rb +5 -5
- data/lib/dscf/credit/version.rb +1 -1
- data/spec/factories/dscf/credit/categories.rb +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9f8c9b62c4ec5893c8ab1b234073b103d9eb78370d133bd1e0b40b56aea1fd0
|
4
|
+
data.tar.gz: 12447006ba8f6896e6316cbf20093b3527454ca144659b00839e435284adea9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5672372c71088c52598cc2839fd5f6b71955ad9b781b3e2c568a37407858b5cdeec1cc37029208000f77cd3bb1d66d9f21a896abda6f48aab182f21436b0fdd
|
7
|
+
data.tar.gz: 630a449898f52513090be1aacb501a29ec977492f67e8a2e097056360ac83188bd632ddf754baaf1a745ebc1660599c29332e1f466b2de5aafffa899888d7f5f
|
@@ -68,7 +68,8 @@ module Dscf::Credit
|
|
68
68
|
:credit_line_id,
|
69
69
|
:credit_limit,
|
70
70
|
:available_limit,
|
71
|
-
:risk
|
71
|
+
:risk,
|
72
|
+
:locked
|
72
73
|
)
|
73
74
|
end
|
74
75
|
|
@@ -77,7 +78,7 @@ module Dscf::Credit
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def allowed_order_columns
|
80
|
-
%w[id credit_limit available_limit risk created_at updated_at loan_profile_id credit_line_id]
|
81
|
+
%w[id credit_limit available_limit risk locked created_at updated_at loan_profile_id credit_line_id]
|
81
82
|
end
|
82
83
|
|
83
84
|
def default_serializer_includes
|
@@ -145,6 +145,24 @@ module Dscf::Credit
|
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
+
def create_loan_profile_for_approved_application(loan_application, score)
|
149
|
+
profile_service = LoanProfileCreationService.new(loan_application, score)
|
150
|
+
profile_result = profile_service.create_loan_profile
|
151
|
+
|
152
|
+
unless profile_result[:success]
|
153
|
+
error_message = "Failed to create loan profile for approved application #{loan_application.id}: #{profile_result[:error]}"
|
154
|
+
Rails.logger.error error_message
|
155
|
+
# Raise error to rollback the entire transaction including score and review status
|
156
|
+
raise StandardError, error_message
|
157
|
+
else
|
158
|
+
Rails.logger.info "Loan profile created successfully for approved application #{loan_application.id}"
|
159
|
+
end
|
160
|
+
|
161
|
+
profile_result
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
|
148
166
|
private
|
149
167
|
|
150
168
|
def update_review_status(loan_application, status)
|
@@ -179,7 +197,7 @@ module Dscf::Credit
|
|
179
197
|
{
|
180
198
|
message: "Automatically rejected based on credit score: #{score}% (<50%)"
|
181
199
|
}
|
182
|
-
when "
|
200
|
+
when "pending"
|
183
201
|
{
|
184
202
|
message: "Manual review required based on credit score: #{score}% (50%-60%)"
|
185
203
|
}
|
@@ -191,22 +209,6 @@ module Dscf::Credit
|
|
191
209
|
end
|
192
210
|
|
193
211
|
# Create loan profile for approved applications
|
194
|
-
def create_loan_profile_for_approved_application(loan_application, score)
|
195
|
-
profile_service = LoanProfileCreationService.new(loan_application, score)
|
196
|
-
profile_result = profile_service.create_loan_profile
|
197
|
-
|
198
|
-
unless profile_result[:success]
|
199
|
-
error_message = "Failed to create loan profile for approved application #{loan_application.id}: #{profile_result[:error]}"
|
200
|
-
Rails.logger.error error_message
|
201
|
-
# Raise error to rollback the entire transaction including score and review status
|
202
|
-
raise StandardError, error_message
|
203
|
-
else
|
204
|
-
Rails.logger.info "Loan profile created successfully for approved application #{loan_application.id}"
|
205
|
-
end
|
206
|
-
|
207
|
-
profile_result
|
208
|
-
end
|
209
|
-
|
210
212
|
def create_loan_profile_from_review(review)
|
211
213
|
loan_application = review.reviewable # Assumes Review belongs_to :reviewable (polymorphic or direct association to LoanApplication)
|
212
214
|
score = loan_application.score # Assumes score is already set on the loan application
|
@@ -1,18 +1,17 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class Category < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_categories"
|
4
|
-
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
4
|
|
6
5
|
has_many :credit_lines, class_name: "Dscf::Credit::CreditLine", foreign_key: "category_id", dependent: :nullify
|
7
6
|
has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "category_id", dependent: :nullify
|
8
7
|
|
9
|
-
validates :
|
10
|
-
validates :name, uniqueness: { scope: :
|
8
|
+
validates :category_type, :name, presence: true
|
9
|
+
validates :name, uniqueness: { scope: :category_type }
|
11
10
|
|
12
|
-
scope :by_type, ->(category_type) { where(
|
11
|
+
scope :by_type, ->(category_type) { where(category_type: category_type) }
|
13
12
|
|
14
13
|
def self.ransackable_attributes(auth_object = nil)
|
15
|
-
%w[id
|
14
|
+
%w[id category_type name description document_reference created_at updated_at]
|
16
15
|
end
|
17
16
|
|
18
17
|
def self.ransackable_associations(auth_object = nil)
|
@@ -16,9 +16,11 @@ module Dscf::Credit
|
|
16
16
|
scope :by_risk_range, ->(min, max) { where(risk: min..max) }
|
17
17
|
scope :by_credit_limit_range, ->(min, max) { where(credit_limit: min..max) }
|
18
18
|
scope :by_available_limit_range, ->(min, max) { where(available_limit: min..max) }
|
19
|
+
scope :locked, -> { where(locked: true) }
|
20
|
+
scope :unlocked, -> { where(locked: false) }
|
19
21
|
|
20
22
|
def self.ransackable_attributes(auth_object = nil)
|
21
|
-
%w[id credit_limit available_limit risk created_at updated_at]
|
23
|
+
%w[id credit_limit available_limit risk locked created_at updated_at]
|
22
24
|
end
|
23
25
|
|
24
26
|
def self.ransackable_associations(auth_object = nil)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class CategorySerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :
|
3
|
+
attributes :id, :category_type, :name, :description, :document_reference, :created_at, :updated_at
|
4
4
|
|
5
5
|
has_many :credit_lines, serializer: Dscf::Credit::CreditLineSerializer
|
6
6
|
has_many :scoring_parameters, serializer: Dscf::Credit::ScoringParameterSerializer
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class EligibleCreditLineSerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :credit_limit, :available_limit, :risk, :created_at, :updated_at
|
3
|
+
attributes :id, :credit_limit, :available_limit, :risk, :locked, :created_at, :updated_at
|
4
4
|
|
5
5
|
belongs_to :loan_profile, serializer: Dscf::Credit::LoanProfileSerializer
|
6
6
|
belongs_to :credit_line, serializer: Dscf::Credit::CreditLineSerializer
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class CreateDscfCreditCategories < ActiveRecord::Migration[8.0]
|
2
2
|
def change
|
3
3
|
create_table :dscf_credit_categories do |t|
|
4
|
-
t.string :
|
4
|
+
t.string :category_type, null: false
|
5
5
|
t.string :name, null: false
|
6
6
|
t.text :description
|
7
7
|
t.string :document_reference
|
@@ -9,9 +9,9 @@ class CreateDscfCreditCategories < ActiveRecord::Migration[8.0]
|
|
9
9
|
t.timestamps
|
10
10
|
end
|
11
11
|
|
12
|
-
add_index :dscf_credit_categories, :
|
12
|
+
add_index :dscf_credit_categories, :category_type
|
13
13
|
add_index :dscf_credit_categories, :name
|
14
14
|
add_index :dscf_credit_categories, :document_reference
|
15
|
-
add_index :dscf_credit_categories, [ :
|
15
|
+
add_index :dscf_credit_categories, [ :category_type, :name ], unique: true
|
16
16
|
end
|
17
17
|
end
|
@@ -6,6 +6,7 @@ class CreateDscfCreditEligibleCreditLines < ActiveRecord::Migration[8.0]
|
|
6
6
|
t.decimal :credit_limit, precision: 15, scale: 2, null: false
|
7
7
|
t.decimal :available_limit, precision: 15, scale: 2, null: false
|
8
8
|
t.decimal :risk, precision: 5, scale: 4, null: true
|
9
|
+
t.boolean :locked, default: false, null: false
|
9
10
|
|
10
11
|
t.timestamps
|
11
12
|
end
|
data/db/seeds.rb
CHANGED
@@ -340,24 +340,24 @@ end
|
|
340
340
|
|
341
341
|
# 4.5. Categories (independent)
|
342
342
|
puts "Seeding categories..."
|
343
|
-
sme_category = Dscf::Credit::Category.find_or_create_by(
|
343
|
+
sme_category = Dscf::Credit::Category.find_or_create_by(category_type: 'credit_line', name: 'SME') do |category|
|
344
344
|
category.description = 'Small and Medium Enterprise credit category'
|
345
345
|
end
|
346
346
|
|
347
|
-
personal_category = Dscf::Credit::Category.find_or_create_by(
|
347
|
+
personal_category = Dscf::Credit::Category.find_or_create_by(category_type: 'credit_line', name: 'Personal') do |category|
|
348
348
|
category.description = 'Personal credit category for individuals'
|
349
349
|
end
|
350
350
|
|
351
|
-
agricultural_category = Dscf::Credit::Category.find_or_create_by(
|
351
|
+
agricultural_category = Dscf::Credit::Category.find_or_create_by(category_type: 'credit_line', name: 'Agricultural') do |category|
|
352
352
|
category.description = 'Agricultural sector credit category'
|
353
353
|
end
|
354
354
|
|
355
|
-
corporate_category = Dscf::Credit::Category.find_or_create_by(
|
355
|
+
corporate_category = Dscf::Credit::Category.find_or_create_by(category_type: 'credit_line', name: 'Corporate') do |category|
|
356
356
|
category.description = 'Corporate credit category for large businesses'
|
357
357
|
end
|
358
358
|
|
359
359
|
# Add eligibility category for scoring
|
360
|
-
eligibility_category = Dscf::Credit::Category.find_or_create_by(
|
360
|
+
eligibility_category = Dscf::Credit::Category.find_or_create_by(category_type: 'eligibility', name: 'default') do |category|
|
361
361
|
category.description = 'Default eligibility category for credit scoring'
|
362
362
|
end
|
363
363
|
|
data/lib/dscf/credit/version.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
FactoryBot.define do
|
2
2
|
factory :category, class: "Dscf::Credit::Category" do
|
3
|
-
|
4
|
-
sequence(:name) { |n| "#{
|
3
|
+
category_type { %w[scoring loan_profile payment risk_assessment].sample }
|
4
|
+
sequence(:name) { |n| "#{category_type.humanize} Category #{n}" }
|
5
5
|
description { Faker::Lorem.paragraph }
|
6
6
|
document_reference { Faker::Alphanumeric.alphanumeric(number: 10).upcase }
|
7
7
|
|
8
8
|
trait :scoring do
|
9
|
-
|
9
|
+
category_type { "scoring" }
|
10
10
|
name { "Scoring Category" }
|
11
11
|
end
|
12
12
|
|
13
13
|
trait :loan_profile do
|
14
|
-
|
14
|
+
category_type { "loan_profile" }
|
15
15
|
name { "Loan Profile Category" }
|
16
16
|
end
|
17
17
|
|
18
18
|
trait :payment do
|
19
|
-
|
19
|
+
category_type { "payment" }
|
20
20
|
name { "Payment Category" }
|
21
21
|
end
|
22
22
|
|
23
23
|
trait :risk_assessment do
|
24
|
-
|
24
|
+
category_type { "risk_assessment" }
|
25
25
|
name { "Risk Assessment Category" }
|
26
26
|
end
|
27
27
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dscf-credit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adoniyas
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-10-
|
10
|
+
date: 2025-10-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: dscf-core
|