dscf-credit 0.1.4 → 0.1.6
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/disbursements_controller.rb +15 -16
- 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/loans_controller.rb +7 -7
- 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.rb +4 -4
- 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/loan_serializer.rb +1 -2
- 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/disbursement_service.rb +39 -84
- 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 +65 -50
- data/config/routes.rb +30 -18
- 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/migrate/20250822092654_create_dscf_credit_loans.rb +3 -1
- data/db/seeds.rb +321 -290
- 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/loans.rb +5 -1
- 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 -20
- data/app/controllers/concerns/dscf/credit/reviewable.rb +0 -112
- data/app/controllers/dscf/credit/payment_requests_controller.rb +0 -87
- data/app/controllers/dscf/credit/payments_controller.rb +0 -36
- data/app/controllers/dscf/credit/scoring_tables_controller.rb +0 -63
- data/app/models/dscf/credit/payment.rb +0 -22
- data/app/models/dscf/credit/payment_request.rb +0 -29
- data/app/models/dscf/credit/scoring_table.rb +0 -24
- data/app/serializers/dscf/credit/payment_request_serializer.rb +0 -10
- data/app/serializers/dscf/credit/payment_serializer.rb +0 -8
- data/app/serializers/dscf/credit/scoring_table_serializer.rb +0 -9
- data/db/migrate/20250822092608_create_dscf_credit_payment_requests.rb +0 -26
- data/db/migrate/20250822092843_create_dscf_credit_payments.rb +0 -23
- data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +0 -18
- data/spec/factories/dscf/credit/payment_requests.rb +0 -40
- data/spec/factories/dscf/credit/payments.rb +0 -39
- data/spec/factories/dscf/credit/scoring_tables.rb +0 -25
@@ -1,23 +1,40 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class ScoringParametersController < ApplicationController
|
3
3
|
include Dscf::Core::Common
|
4
|
-
include Dscf::
|
4
|
+
include Dscf::Core::ReviewableController
|
5
5
|
|
6
6
|
def create
|
7
7
|
super do
|
8
8
|
scoring_parameter = @clazz.new(model_params)
|
9
9
|
scoring_parameter.created_by = current_user
|
10
|
-
scoring_parameter.
|
10
|
+
scoring_parameter.reviews.build(context: "default", status: "pending")
|
11
11
|
|
12
|
-
scoring_parameter
|
12
|
+
if validate_category_weight_limit(scoring_parameter)
|
13
|
+
scoring_parameter
|
14
|
+
else
|
15
|
+
scoring_parameter.errors.add(:weight, "would exceed the total weight limit of 1.0 for this category")
|
16
|
+
render_error(errors: scoring_parameter.errors.full_messages, status: :unprocessable_entity)
|
17
|
+
return
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
22
|
+
def update
|
23
|
+
unless validate_category_weight_limit(@obj, exclude_current: true)
|
24
|
+
@obj.errors.add(:weight, "would exceed the total weight limit of 1.0 for this category")
|
25
|
+
render_error(errors: @obj.errors.full_messages, status: :unprocessable_entity)
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
16
32
|
private
|
17
33
|
|
18
34
|
def model_params
|
19
35
|
params.require(:scoring_parameter).permit(
|
20
36
|
:bank_id,
|
37
|
+
:category_id,
|
21
38
|
:name,
|
22
39
|
:description,
|
23
40
|
:data_type,
|
@@ -26,30 +43,59 @@ module Dscf::Credit
|
|
26
43
|
:max_value,
|
27
44
|
:active,
|
28
45
|
:previous_version_id,
|
29
|
-
:review_date,
|
30
46
|
:source,
|
31
47
|
:scoring_param_type_id,
|
32
|
-
:document_reference
|
33
|
-
:status,
|
34
|
-
:review_feedback
|
48
|
+
:document_reference
|
35
49
|
)
|
36
50
|
end
|
37
51
|
|
38
52
|
def eager_loaded_associations
|
39
|
-
[
|
53
|
+
[
|
54
|
+
:bank, :category, :created_by, :scoring_param_type, :previous_version, :parameter_normalizers,
|
55
|
+
reviews: { reviewed_by: :user_profile }
|
56
|
+
]
|
40
57
|
end
|
41
58
|
|
42
59
|
def allowed_order_columns
|
43
|
-
%w[id name data_type weight active
|
60
|
+
%w[id name data_type weight active created_at updated_at]
|
44
61
|
end
|
45
62
|
|
46
63
|
def default_serializer_includes
|
47
64
|
{
|
48
|
-
index: [ :bank ],
|
49
|
-
show: [
|
50
|
-
|
51
|
-
|
65
|
+
index: [ :bank, :category, reviews: { reviewed_by: :user_profile } ],
|
66
|
+
show: [
|
67
|
+
:bank, :category, :created_by, :scoring_param_type, :previous_version, :parameter_normalizers,
|
68
|
+
reviews: { reviewed_by: :user_profile }
|
69
|
+
],
|
70
|
+
create: [ :bank, :category, :created_by, :scoring_param_type ],
|
71
|
+
update: [
|
72
|
+
:bank, :category, :created_by, :scoring_param_type, :parameter_normalizers,
|
73
|
+
reviews: { reviewed_by: :user_profile }
|
74
|
+
]
|
52
75
|
}
|
53
76
|
end
|
77
|
+
|
78
|
+
def validate_category_weight_limit(scoring_parameter, exclude_current: false)
|
79
|
+
return true unless scoring_parameter.category_id && scoring_parameter.weight
|
80
|
+
|
81
|
+
# Get existing parameters in the same category for the same bank
|
82
|
+
existing_params = ScoringParameter.where(
|
83
|
+
bank_id: scoring_parameter.bank_id,
|
84
|
+
category_id: scoring_parameter.category_id,
|
85
|
+
active: true
|
86
|
+
)
|
87
|
+
|
88
|
+
# Exclude current parameter from the calculation when updating
|
89
|
+
if exclude_current && scoring_parameter.persisted?
|
90
|
+
existing_params = existing_params.where.not(id: scoring_parameter.id)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Calculate total weight
|
94
|
+
current_total_weight = existing_params.sum(:weight)
|
95
|
+
new_total_weight = current_total_weight + scoring_parameter.weight.to_f
|
96
|
+
|
97
|
+
# Allow small floating point tolerance (e.g., 1.0001 should be acceptable)
|
98
|
+
new_total_weight <= 1.001
|
99
|
+
end
|
54
100
|
end
|
55
101
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class SystemConfigsController < ApplicationController
|
3
3
|
include Dscf::Core::Common
|
4
|
-
include Dscf::
|
4
|
+
include Dscf::Core::ReviewableController
|
5
5
|
|
6
6
|
def create
|
7
7
|
super do
|
8
8
|
obj = @clazz.new(model_params)
|
9
|
-
obj.reviewed_by = current_user
|
10
9
|
obj.last_updated_by = current_user
|
10
|
+
obj.reviews.build(context: "default", status: "pending")
|
11
|
+
|
11
12
|
obj
|
12
13
|
end
|
13
14
|
end
|
@@ -25,27 +26,44 @@ module Dscf::Credit
|
|
25
26
|
def model_params
|
26
27
|
params.require(:system_config).permit(
|
27
28
|
:config_definition_id,
|
28
|
-
:config_value
|
29
|
-
:status,
|
30
|
-
:review_date,
|
31
|
-
:review_feedback
|
29
|
+
:config_value
|
32
30
|
)
|
33
31
|
end
|
34
32
|
|
35
33
|
def eager_loaded_associations
|
36
|
-
[
|
34
|
+
[
|
35
|
+
:config_definition,
|
36
|
+
:last_updated_by,
|
37
|
+
reviews: { reviewed_by: :user_profile }
|
38
|
+
]
|
37
39
|
end
|
38
40
|
|
39
41
|
def allowed_order_columns
|
40
|
-
%w[id config_value
|
42
|
+
%w[id config_value created_at updated_at]
|
41
43
|
end
|
42
44
|
|
43
45
|
def default_serializer_includes
|
44
46
|
{
|
45
|
-
index: [
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
index: [
|
48
|
+
:config_definition,
|
49
|
+
reviews: { reviewed_by: :user_profile }
|
50
|
+
],
|
51
|
+
show: [
|
52
|
+
:config_definition,
|
53
|
+
:last_updated_by,
|
54
|
+
reviews: { reviewed_by: :user_profile }
|
55
|
+
],
|
56
|
+
create: [
|
57
|
+
:config_definition,
|
58
|
+
:last_updated_by,
|
59
|
+
:reviews
|
60
|
+
|
61
|
+
],
|
62
|
+
update: [
|
63
|
+
:config_definition,
|
64
|
+
:last_updated_by,
|
65
|
+
reviews: { reviewed_by: :user_profile }
|
66
|
+
]
|
49
67
|
}
|
50
68
|
end
|
51
69
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Core
|
3
|
+
module ReviewableModel
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_many :reviews, as: :reviewable, class_name: "Dscf::Core::Review", dependent: :destroy
|
8
|
+
end
|
9
|
+
|
10
|
+
def review_for(context = :default)
|
11
|
+
reviews.with_context(context).order(created_at: :desc)
|
12
|
+
end
|
13
|
+
|
14
|
+
def current_review_for(context = :default)
|
15
|
+
review_for(context).first
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_status_for(context = :default)
|
19
|
+
current_review = current_review_for(context)
|
20
|
+
return current_review.status if current_review
|
21
|
+
|
22
|
+
# Return default initial status for zero-config
|
23
|
+
"pending"
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_review_for(context = :default)
|
27
|
+
reviews.build(context: context.to_s)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -13,10 +13,10 @@ module Dscf::Credit
|
|
13
13
|
foreign_key: "bank_id", dependent: :destroy
|
14
14
|
has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter",
|
15
15
|
foreign_key: "bank_id", dependent: :destroy
|
16
|
-
has_many :
|
17
|
-
foreign_key: "bank_id", dependent: :destroy
|
18
|
-
has_many :facilitators, class_name: "Dscf::Credit::Facilitator",
|
16
|
+
has_many :loan_applications, class_name: "Dscf::Credit::LoanApplication",
|
19
17
|
foreign_key: "bank_id", dependent: :destroy
|
18
|
+
has_many :facilitators, through: :facilitator_applications, class_name: "Dscf::Credit::Facilitator"
|
19
|
+
has_many :facilitator_applications, class_name: "Dscf::Credit::FacilitatorApplication"
|
20
20
|
has_many :bank_staffs, through: :bank_branches, class_name: "Dscf::Credit::BankStaff"
|
21
21
|
|
22
22
|
validates :name, presence: true
|
@@ -4,7 +4,7 @@ module Dscf::Credit
|
|
4
4
|
|
5
5
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
6
|
has_many :bank_staffs, class_name: "Dscf::Credit::BankStaff", foreign_key: "bank_branch_id", dependent: :destroy
|
7
|
-
has_many :
|
7
|
+
has_many :loan_applications, class_name: "Dscf::Credit::LoanApplication", foreign_key: "review_branch_id", dependent: :nullify
|
8
8
|
|
9
9
|
validates :branch_name, presence: true
|
10
10
|
validates :branch_name, uniqueness: { scope: :bank_id }
|
@@ -4,8 +4,7 @@ module Dscf::Credit
|
|
4
4
|
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
5
|
|
6
6
|
has_many :credit_lines, class_name: "Dscf::Credit::CreditLine", foreign_key: "category_id", dependent: :nullify
|
7
|
-
has_many :
|
8
|
-
has_many :scoring_parameters, through: :scoring_tables
|
7
|
+
has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "category_id", dependent: :nullify
|
9
8
|
|
10
9
|
validates :type, :name, presence: true
|
11
10
|
validates :name, uniqueness: { scope: :type }
|
@@ -2,10 +2,11 @@ module Dscf::Credit
|
|
2
2
|
class CreditLine < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_credit_lines"
|
4
4
|
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
5
7
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
8
|
belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
|
7
9
|
belongs_to :created_by, polymorphic: true
|
8
|
-
belongs_to :reviewed_by, polymorphic: true, optional: true
|
9
10
|
|
10
11
|
has_many :credit_line_specs, class_name: "Dscf::Credit::CreditLineSpec", foreign_key: "credit_line_id", dependent: :destroy
|
11
12
|
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "credit_line_id", dependent: :destroy
|
@@ -14,20 +15,13 @@ module Dscf::Credit
|
|
14
15
|
|
15
16
|
validates :name, presence: true
|
16
17
|
validates :code, uniqueness: { scope: :bank_id }, allow_blank: true
|
17
|
-
validates :status, inclusion: { in: %w[pending approved active suspended rejected modify] }
|
18
|
-
enum :status, { pending: "pending", approved: "approved", rejected: "rejected", modify: "modify", active: "active", suspended: "suspended" }
|
19
|
-
|
20
|
-
|
21
|
-
scope :active, -> { where(status: "active") }
|
22
|
-
scope :approved, -> { where(status: "approved") }
|
23
|
-
scope :pending, -> { where(status: "pending") }
|
24
18
|
|
25
19
|
def self.ransackable_attributes(auth_object = nil)
|
26
|
-
%w[id name code description
|
20
|
+
%w[id name code description document_reference created_at updated_at]
|
27
21
|
end
|
28
22
|
|
29
23
|
def self.ransackable_associations(auth_object = nil)
|
30
|
-
%w[bank category created_by
|
24
|
+
%w[bank category created_by credit_line_specs loans eligible_credit_lines scoring_parameters reviews]
|
31
25
|
end
|
32
26
|
end
|
33
27
|
end
|
@@ -6,10 +6,10 @@ module Dscf::Credit
|
|
6
6
|
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
7
7
|
|
8
8
|
validates :credit_limit, presence: true
|
9
|
-
validates :credit_limit, numericality: {
|
9
|
+
validates :credit_limit, numericality: { greater_than_or_equal_to: 0 }
|
10
10
|
validates :available_limit, presence: true
|
11
11
|
validates :available_limit, numericality: { greater_than_or_equal_to: 0 }
|
12
|
-
validates :risk, numericality: { greater_than_or_equal_to: 0.
|
12
|
+
validates :risk, numericality: { greater_than_or_equal_to: 0.0, less_than_or_equal_to: 0.9 }, allow_nil: true
|
13
13
|
|
14
14
|
scope :by_loan_profile, ->(loan_profile_id) { where(loan_profile_id: loan_profile_id) }
|
15
15
|
scope :by_credit_line, ->(credit_line_id) { where(credit_line_id: credit_line_id) }
|
@@ -1,32 +1,21 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class Facilitator < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_facilitators"
|
4
|
-
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
|
-
end
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
7
|
+
belongs_to :facilitator_application, class_name: "Dscf::Credit::FacilitatorApplication", foreign_key: "facilitator_application_id"
|
11
8
|
has_many :facilitator_performances, class_name: "Dscf::Credit::FacilitatorPerformance", foreign_key: "facilitator_id", dependent: :destroy
|
12
9
|
|
13
|
-
validates :name, :type, presence: true
|
14
|
-
validates :type, inclusion: { in: %w[individual corporate agent] }
|
15
|
-
validates :user_id, uniqueness: { scope: :bank_id }
|
16
10
|
validates :total_limit, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
17
|
-
|
18
|
-
enum :kyc_status, { pending: "pending", approved: "approved", rejected: "rejected" }
|
19
|
-
|
20
|
-
scope :approved, -> { where(kyc_status: "approved") }
|
21
|
-
scope :pending_kyc, -> { where(kyc_status: "pending") }
|
22
|
-
scope :rejected, -> { where(kyc_status: "rejected") }
|
11
|
+
validates :facilitator_application_id, uniqueness: true
|
23
12
|
|
24
13
|
def self.ransackable_attributes(auth_object = nil)
|
25
|
-
%w[id
|
14
|
+
%w[id total_limit created_at updated_at facilitator_application_id]
|
26
15
|
end
|
27
16
|
|
28
17
|
def self.ransackable_associations(auth_object = nil)
|
29
|
-
%w[
|
18
|
+
%w[facilitator_application facilitator_performances reviews]
|
30
19
|
end
|
31
20
|
end
|
32
21
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class FacilitatorApplication < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_facilitator_applications"
|
4
|
+
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
7
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
8
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
9
|
+
|
10
|
+
validates :facilitator_info, presence: true
|
11
|
+
|
12
|
+
def self.ransackable_attributes(auth_object = nil)
|
13
|
+
%w[id user_id bank_id created_at updated_at]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.ransackable_associations(auth_object = nil)
|
17
|
+
%w[user bank reviews]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -4,7 +4,6 @@ module Dscf::Credit
|
|
4
4
|
|
5
5
|
belongs_to :loan_profile, class_name: "Dscf::Credit::LoanProfile", foreign_key: "loan_profile_id"
|
6
6
|
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
7
|
-
belongs_to :payment_request, class_name: "Dscf::Credit::PaymentRequest", foreign_key: "payment_request_id"
|
8
7
|
has_many :loan_transactions, class_name: "Dscf::Credit::LoanTransaction", foreign_key: "loan_id", dependent: :destroy
|
9
8
|
has_many :daily_routine_transactions, class_name: "Dscf::Credit::DailyRoutineTransaction", foreign_key: "loan_id", dependent: :destroy
|
10
9
|
|
@@ -13,18 +12,19 @@ module Dscf::Credit
|
|
13
12
|
validates :accrued_interest, :accrued_penalty, :facilitation_fee, numericality: { greater_than_or_equal_to: 0 }
|
14
13
|
validates :status, inclusion: { in: %w[pending approved disbursed active overdue paid closed] }
|
15
14
|
|
16
|
-
scope :active, -> { where(
|
15
|
+
scope :active, -> { where(active: true) }
|
16
|
+
scope :inactive, -> { where(active: false) }
|
17
17
|
scope :overdue, -> { where(status: "overdue") }
|
18
18
|
scope :paid, -> { where(status: "paid") }
|
19
19
|
scope :due_today, -> { where(due_date: Date.current) }
|
20
20
|
scope :past_due, -> { where("due_date < ? AND status IN (?)", Date.current, [ "active", "overdue" ]) }
|
21
21
|
|
22
22
|
def self.ransackable_attributes(auth_object = nil)
|
23
|
-
%w[id status principal_amount accrued_interest accrued_penalty facilitation_fee total_loan_amount remaining_amount due_date disbursed_at created_at updated_at]
|
23
|
+
%w[id status principal_amount accrued_interest accrued_penalty facilitation_fee total_loan_amount remaining_amount due_date disbursed_at active created_at updated_at]
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.ransackable_associations(auth_object = nil)
|
27
|
-
%w[loan_profile credit_line
|
27
|
+
%w[loan_profile credit_line loan_transactions daily_routine_transactions]
|
28
28
|
end
|
29
29
|
|
30
30
|
delegate :user, to: :loan_profile, allow_nil: true
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class LoanApplication < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_loan_applications"
|
4
|
+
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
7
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
8
|
+
if defined?(Dscf::Core::User)
|
9
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
|
+
end
|
11
|
+
belongs_to :backer, polymorphic: true
|
12
|
+
belongs_to :review_branch, class_name: "Dscf::Credit::BankBranch", foreign_key: "review_branch_id"
|
13
|
+
|
14
|
+
has_one :loan_profile, class_name: "Dscf::Credit::LoanProfile", foreign_key: "loan_application_id", dependent: :destroy
|
15
|
+
|
16
|
+
has_many_attached :bank_statement_attachments
|
17
|
+
|
18
|
+
validates :bank_statement_source, presence: true, inclusion: { in: %w[internal external] }
|
19
|
+
validates :user_info, presence: true
|
20
|
+
validates :score, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }, allow_nil: true
|
21
|
+
|
22
|
+
def self.ransackable_attributes(auth_object = nil)
|
23
|
+
%w[id bank_statement_source score created_at updated_at]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ransackable_associations(auth_object = nil)
|
27
|
+
%w[bank user backer review_branch loan_profile reviews]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,46 +2,26 @@ module Dscf::Credit
|
|
2
2
|
class LoanProfile < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_loan_profiles"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
belongs_to :
|
8
|
-
belongs_to :backer, polymorphic: true, optional: true
|
9
|
-
if defined?(Dscf::Core::User)
|
10
|
-
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
11
|
-
end
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
7
|
+
belongs_to :loan_application, class_name: "Dscf::Credit::LoanApplication", foreign_key: "loan_application_id"
|
12
8
|
has_many :loan_profile_scoring_specs, class_name: "Dscf::Credit::LoanProfileScoringSpec", foreign_key: "loan_profile_id", dependent: :destroy
|
13
9
|
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "loan_profile_id", dependent: :destroy
|
14
10
|
has_many :eligible_credit_lines, class_name: "Dscf::Credit::EligibleCreditLine", foreign_key: "loan_profile_id", dependent: :destroy
|
15
11
|
|
16
|
-
validates :
|
17
|
-
|
18
|
-
validates :
|
19
|
-
validate :available_amount_not_greater_than_total_amount
|
12
|
+
validates :score, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }, allow_nil: true
|
13
|
+
validates :total_limit, numericality: { greater_than_or_equal_to: 0 }
|
14
|
+
validates :code, presence: true, uniqueness: true, length: { maximum: 8 }, format: { with: /\ABB\d{0,6}\z/, message: "must start with BB followed by up to 6 digits" }
|
20
15
|
|
21
|
-
scope :
|
22
|
-
scope :
|
23
|
-
scope :rejected, -> { where(status: "rejected") }
|
24
|
-
scope :manual_review, -> { where(status: "manual_review") }
|
25
|
-
scope :kyc_approved, -> { where(status: "kyc_approved") }
|
26
|
-
scope :kyc_rejected, -> { where(status: "kyc_rejected") }
|
27
|
-
scope :with_available_amount, -> { where("available_amount > 0") }
|
28
|
-
scope :by_total_amount_range, ->(min, max) { where(total_amount: min..max) }
|
29
|
-
scope :by_available_amount_range, ->(min, max) { where(available_amount: min..max) }
|
16
|
+
scope :with_score_range, ->(min, max) { where(score: min..max) }
|
17
|
+
scope :by_total_limit_range, ->(min, max) { where(total_limit: min..max) }
|
30
18
|
|
31
19
|
def self.ransackable_attributes(auth_object = nil)
|
32
|
-
%w[id
|
20
|
+
%w[id code score total_limit created_at updated_at loan_application_id]
|
33
21
|
end
|
34
22
|
|
35
23
|
def self.ransackable_associations(auth_object = nil)
|
36
|
-
%w[
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def available_amount_not_greater_than_total_amount
|
42
|
-
return unless total_amount && available_amount
|
43
|
-
|
44
|
-
errors.add(:available_amount, "cannot be greater than total amount") if available_amount > total_amount
|
24
|
+
%w[loan_application loan_profile_scoring_specs loans eligible_credit_lines reviews]
|
45
25
|
end
|
46
26
|
end
|
47
27
|
end
|
@@ -6,6 +6,6 @@ module Dscf::Credit
|
|
6
6
|
|
7
7
|
validates :name, :raw_value, :normalized_value, presence: true
|
8
8
|
validates :raw_value, uniqueness: { scope: :scoring_parameter_id }
|
9
|
-
validates :normalized_value, numericality: { greater_than_or_equal_to: 0 }
|
9
|
+
validates :normalized_value, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1 }
|
10
10
|
end
|
11
11
|
end
|
@@ -2,30 +2,28 @@ module Dscf::Credit
|
|
2
2
|
class ScoringParameter < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_scoring_parameters"
|
4
4
|
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
5
7
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
8
|
+
belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
|
6
9
|
belongs_to :created_by, polymorphic: true
|
7
|
-
belongs_to :reviewed_by, polymorphic: true
|
8
10
|
belongs_to :scoring_param_type, class_name: "Dscf::Credit::ScoringParamType", foreign_key: "scoring_param_type_id"
|
9
11
|
belongs_to :previous_version, class_name: "Dscf::Credit::ScoringParameter", optional: true
|
10
12
|
has_many :parameter_normalizers, class_name: "Dscf::Credit::ParameterNormalizer", foreign_key: "scoring_parameter_id", dependent: :destroy
|
11
|
-
has_many :scoring_tables, class_name: "Dscf::Credit::ScoringTable", foreign_key: "scoring_parameter_id", dependent: :destroy
|
12
|
-
has_many :categories, through: :scoring_tables
|
13
13
|
|
14
14
|
validates :name, :data_type, :weight, presence: true
|
15
15
|
validates :weight, numericality: { greater_than: 0, less_than_or_equal_to: 1 }
|
16
16
|
validates :data_type, inclusion: { in: %w[integer decimal boolean string] }
|
17
17
|
validates :name, uniqueness: { scope: [ :bank_id, :active ] }
|
18
|
-
validates :status, inclusion: { in: %w[pending approved rejected modify] }
|
19
|
-
enum :status, { pending: "pending", approved: "approved", rejected: "rejected", modify: "modify" }
|
20
18
|
|
21
19
|
scope :active, -> { where(active: true) }
|
22
20
|
|
23
21
|
def self.ransackable_attributes(auth_object = nil)
|
24
|
-
%w[id name description data_type weight min_value max_value active
|
22
|
+
%w[id name description data_type weight min_value max_value active source document_reference created_at updated_at]
|
25
23
|
end
|
26
24
|
|
27
25
|
def self.ransackable_associations(auth_object = nil)
|
28
|
-
%w[bank created_by
|
26
|
+
%w[bank created_by scoring_param_type previous_version parameter_normalizers categories reviews]
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
@@ -2,25 +2,20 @@ module Dscf::Credit
|
|
2
2
|
class SystemConfig < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_system_configs"
|
4
4
|
|
5
|
+
include Dscf::Core::ReviewableModel
|
6
|
+
|
5
7
|
belongs_to :config_definition, class_name: "Dscf::Credit::SystemConfigDefinition", foreign_key: "config_definition_id"
|
6
8
|
belongs_to :last_updated_by, polymorphic: true
|
7
|
-
belongs_to :reviewed_by, polymorphic: true
|
8
9
|
|
9
10
|
validates :config_value, presence: true
|
10
|
-
validates :status, inclusion: { in: %w[pending approved rejected modify] }
|
11
|
-
enum :status, { pending: "pending", approved: "approved", rejected: "rejected", modify: "modify" }
|
12
11
|
validates :config_definition_id, uniqueness: true
|
13
12
|
|
14
|
-
scope :pending, -> { where(status: "pending") }
|
15
|
-
scope :approved, -> { where(status: "approved") }
|
16
|
-
scope :rejected, -> { where(status: "rejected") }
|
17
|
-
|
18
13
|
def self.ransackable_attributes(auth_object = nil)
|
19
|
-
%w[id config_value
|
14
|
+
%w[id config_value created_at updated_at]
|
20
15
|
end
|
21
16
|
|
22
17
|
def self.ransackable_associations(auth_object = nil)
|
23
|
-
%w[config_definition last_updated_by
|
18
|
+
%w[config_definition last_updated_by reviews]
|
24
19
|
end
|
25
20
|
end
|
26
21
|
end
|
@@ -3,7 +3,6 @@ module Dscf::Credit
|
|
3
3
|
attributes :id, :type, :name, :description, :document_reference, :created_at, :updated_at
|
4
4
|
|
5
5
|
has_many :credit_lines, serializer: Dscf::Credit::CreditLineSerializer
|
6
|
-
has_many :scoring_tables, serializer: Dscf::Credit::ScoringTableSerializer
|
7
6
|
has_many :scoring_parameters, serializer: Dscf::Credit::ScoringParameterSerializer
|
8
7
|
end
|
9
8
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class CreditLineSerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :name, :code, :description, :
|
3
|
+
attributes :id, :name, :code, :description, :document_reference,
|
4
4
|
:created_at, :updated_at
|
5
5
|
|
6
6
|
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
7
|
belongs_to :category, serializer: Dscf::Credit::CategorySerializer
|
8
8
|
belongs_to :created_by, serializer: Dscf::Core::UserSerializer
|
9
|
-
belongs_to :reviewed_by, serializer: Dscf::Core::UserSerializer
|
10
9
|
has_many :credit_line_specs, serializer: Dscf::Credit::CreditLineSpecSerializer
|
11
10
|
has_many :loans, serializer: Dscf::Credit::LoanSerializer
|
12
11
|
has_many :eligible_credit_lines, serializer: Dscf::Credit::EligibleCreditLineSerializer
|
12
|
+
has_many :reviews, serializer: Dscf::Core::ReviewSerializer
|
13
13
|
end
|
14
14
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class Dscf::Credit::FacilitatorApplicationSerializer < ActiveModel::Serializer
|
2
|
+
attributes :id, :user_id, :bank_id, :facilitator_info, :created_at, :updated_at
|
3
|
+
|
4
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
5
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
6
|
+
has_many :reviews, serializer: Dscf::Core::ReviewSerializer
|
7
|
+
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class FacilitatorSerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :
|
4
|
-
:created_at, :updated_at
|
3
|
+
attributes :id, :total_limit, :created_at, :updated_at
|
5
4
|
|
6
|
-
belongs_to :
|
7
|
-
|
8
|
-
belongs_to :kyc_reviewed_by, polymorphic: true
|
9
|
-
has_many :facilitator_performances, serializer: Dscf::Credit::FacilitatorPerformanceSerializer
|
5
|
+
belongs_to :facilitator_application, serializer: Dscf::Credit::FacilitatorApplicationSerializer
|
6
|
+
has_many :reviews, serializer: Dscf::Core::ReviewSerializer
|
10
7
|
end
|
11
8
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class LoanApplicationSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :bank_statement_source, :score, :user_info, :facilitator_info,
|
4
|
+
:bank_info, :field_assessment, :created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
8
|
+
belongs_to :backer, polymorphic: true
|
9
|
+
belongs_to :review_branch, serializer: Dscf::Credit::BankBranchSerializer
|
10
|
+
has_many :reviews, serializer: Dscf::Core::ReviewSerializer
|
11
|
+
end
|
12
|
+
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class LoanProfileSerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :
|
3
|
+
attributes :id, :code, :score, :total_limit, :created_at, :updated_at
|
4
4
|
|
5
|
-
belongs_to :
|
6
|
-
belongs_to :review_branch, serializer: Dscf::Credit::BankBranchSerializer
|
7
|
-
belongs_to :reviewed_by
|
8
|
-
belongs_to :backer
|
9
|
-
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
5
|
+
belongs_to :loan_application, serializer: Dscf::Credit::LoanApplicationSerializer
|
10
6
|
|
7
|
+
has_many :reviews, serializer: Dscf::Core::ReviewSerializer
|
11
8
|
has_many :loan_profile_scoring_specs, serializer: Dscf::Credit::LoanProfileScoringSpecSerializer
|
12
9
|
has_many :loans, serializer: Dscf::Credit::LoanSerializer
|
13
10
|
has_many :eligible_credit_lines, serializer: Dscf::Credit::EligibleCreditLineSerializer
|