dscf-credit 0.1.1 → 0.1.3
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/authenticatable.rb +81 -0
- data/app/controllers/concerns/dscf/core/common.rb +200 -0
- data/app/controllers/concerns/dscf/core/filterable.rb +12 -0
- data/app/controllers/concerns/dscf/core/json_response.rb +77 -0
- data/app/controllers/concerns/dscf/core/pagination.rb +71 -0
- data/app/controllers/concerns/dscf/core/token_authenticatable.rb +53 -0
- data/app/controllers/concerns/dscf/credit/reviewable.rb +112 -0
- data/app/controllers/dscf/credit/categories_controller.rb +6 -5
- data/app/controllers/dscf/credit/credit_limit_calculations_controller.rb +50 -0
- data/app/controllers/dscf/credit/credit_line_specs_controller.rb +2 -1
- data/app/controllers/dscf/credit/credit_lines_controller.rb +11 -38
- data/app/controllers/dscf/credit/disbursements_controller.rb +55 -0
- data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +50 -0
- data/app/controllers/dscf/credit/facilitators_controller.rb +39 -150
- data/app/controllers/dscf/credit/loan_profiles_controller.rb +138 -0
- data/app/controllers/dscf/credit/payment_requests_controller.rb +54 -5
- data/app/controllers/dscf/credit/repayments_controller.rb +53 -0
- data/app/controllers/dscf/credit/scoring_param_types_controller.rb +31 -0
- data/app/controllers/dscf/credit/scoring_parameters_controller.rb +13 -8
- data/app/controllers/dscf/credit/scoring_tables_controller.rb +8 -8
- data/app/controllers/dscf/credit/system_configs_controller.rb +10 -7
- data/app/models/dscf/credit/bank_branch.rb +2 -1
- data/app/models/dscf/credit/category.rb +4 -2
- data/app/models/dscf/credit/credit_line.rb +9 -6
- data/app/models/dscf/credit/credit_line_spec.rb +3 -3
- data/app/models/dscf/credit/eligible_credit_line.rb +28 -0
- data/app/models/dscf/credit/facilitator.rb +5 -4
- data/app/models/dscf/credit/facilitator_performance.rb +1 -2
- data/app/models/dscf/credit/loan_profile.rb +8 -4
- data/app/models/dscf/credit/loan_profile_scoring_spec.rb +4 -6
- data/app/models/dscf/credit/scoring_param_type.rb +17 -0
- data/app/models/dscf/credit/scoring_parameter.rb +8 -7
- data/app/models/dscf/credit/scoring_table.rb +4 -4
- data/app/models/dscf/credit/system_config.rb +5 -4
- data/app/serializers/dscf/credit/bank_branch_serializer.rb +1 -0
- data/app/serializers/dscf/credit/category_serializer.rb +3 -1
- data/app/serializers/dscf/credit/credit_line_serializer.rb +4 -2
- data/app/serializers/dscf/credit/credit_line_spec_serializer.rb +1 -1
- data/app/serializers/dscf/credit/daily_routine_transaction_serializer.rb +8 -0
- data/app/serializers/dscf/credit/eligible_credit_line_serializer.rb +8 -0
- data/app/serializers/dscf/credit/facilitator_performance_serializer.rb +1 -1
- data/app/serializers/dscf/credit/facilitator_serializer.rb +2 -2
- data/app/serializers/dscf/credit/loan_profile_scoring_spec_serializer.rb +8 -0
- data/app/serializers/dscf/credit/loan_profile_serializer.rb +15 -0
- data/app/serializers/dscf/credit/loan_serializer.rb +12 -0
- data/app/serializers/dscf/credit/loan_transaction_serializer.rb +8 -0
- data/app/serializers/dscf/credit/payment_request_serializer.rb +10 -0
- data/app/serializers/dscf/credit/payment_serializer.rb +8 -0
- data/app/serializers/dscf/credit/scoring_param_type_serializer.rb +7 -0
- data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +6 -3
- data/app/serializers/dscf/credit/scoring_table_serializer.rb +1 -1
- data/app/serializers/dscf/credit/system_config_serializer.rb +2 -2
- data/app/services/dscf/credit/credit_limit_calculation_service.rb +153 -0
- data/app/services/dscf/credit/disbursement_service.rb +180 -0
- data/app/services/dscf/credit/facilitator_approval_service.rb +4 -3
- data/app/services/dscf/credit/facilitator_creation_service.rb +157 -0
- data/app/services/dscf/credit/repayment_service.rb +216 -0
- data/app/services/dscf/credit/risk_application_service.rb +27 -0
- data/app/services/dscf/credit/scoring_service.rb +297 -0
- data/config/locales/en.yml +125 -8
- data/config/routes.rb +42 -11
- data/db/migrate/20250822091011_create_dscf_credit_categories.rb +2 -0
- data/db/migrate/20250822091131_create_dscf_credit_credit_lines.rb +7 -4
- data/db/migrate/20250822091527_create_dscf_credit_credit_line_specs.rb +1 -0
- data/db/migrate/20250822091820_create_dscf_credit_system_configs.rb +5 -2
- data/db/migrate/20250822092040_create_dscf_credit_scoring_param_types.rb +12 -0
- data/db/migrate/20250822092050_create_dscf_credit_scoring_parameters.rb +11 -6
- data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +6 -3
- data/db/migrate/20250822092417_create_dscf_credit_loan_profile_scoring_specs.rb +5 -7
- data/db/migrate/20250822092436_create_dscf_credit_facilitators.rb +5 -2
- data/db/migrate/20250822092528_create_dscf_credit_facilitator_performances.rb +0 -3
- data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +2 -2
- data/db/migrate/20250917120000_create_dscf_credit_eligible_credit_lines.rb +18 -0
- data/db/seeds.rb +134 -40
- data/lib/dscf/credit/version.rb +1 -1
- data/spec/factories/dscf/credit/categories.rb +1 -0
- data/spec/factories/dscf/credit/credit_line_specs.rb +1 -0
- data/spec/factories/dscf/credit/credit_lines.rb +9 -7
- data/spec/factories/dscf/credit/eligible_credit_lines.rb +33 -0
- data/spec/factories/dscf/credit/facilitator_performances.rb +0 -5
- data/spec/factories/dscf/credit/facilitators.rb +6 -1
- data/spec/factories/dscf/credit/loan_profile_scoring_specs.rb +1 -7
- data/spec/factories/dscf/credit/loan_profiles.rb +11 -6
- data/spec/factories/dscf/credit/scoring_param_types.rb +31 -0
- data/spec/factories/dscf/credit/scoring_parameters.rb +26 -4
- data/spec/factories/dscf/credit/scoring_tables.rb +1 -1
- data/spec/factories/dscf/credit/system_configs.rb +8 -2
- metadata +50 -2
@@ -0,0 +1,53 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class RepaymentsController < ApplicationController
|
3
|
+
def create
|
4
|
+
loan = Dscf::Credit::Loan.find(params[:loan_id])
|
5
|
+
payment_amount = params[:amount].to_f
|
6
|
+
|
7
|
+
service = Dscf::Credit::RepaymentService.new(loan, payment_amount, current_user)
|
8
|
+
result = service.process_repayment
|
9
|
+
|
10
|
+
if result[:success]
|
11
|
+
render_success(
|
12
|
+
"repayment.success.create",
|
13
|
+
data: {
|
14
|
+
loan: result[:loan],
|
15
|
+
payment_details: result[:payment_details]
|
16
|
+
},
|
17
|
+
serializer_options: {
|
18
|
+
include: [
|
19
|
+
:loan_profile,
|
20
|
+
:credit_line,
|
21
|
+
:payment_request,
|
22
|
+
:loan_transactions
|
23
|
+
]
|
24
|
+
}
|
25
|
+
)
|
26
|
+
else
|
27
|
+
render_error(
|
28
|
+
"repayment.errors.create",
|
29
|
+
errors: [ result[:error] ],
|
30
|
+
status: :unprocessable_entity
|
31
|
+
)
|
32
|
+
end
|
33
|
+
rescue ActiveRecord::RecordNotFound => e
|
34
|
+
render_error(
|
35
|
+
"repayment.errors.not_found",
|
36
|
+
errors: [ e.message ],
|
37
|
+
status: :not_found
|
38
|
+
)
|
39
|
+
rescue StandardError => e
|
40
|
+
render_error(
|
41
|
+
"repayment.errors.create",
|
42
|
+
errors: [ e.message ],
|
43
|
+
status: :internal_server_error
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def model_params
|
50
|
+
params.permit(:loan_id, :amount)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringParamTypesController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def model_params
|
8
|
+
params.require(:scoring_param_type).permit(
|
9
|
+
:name,
|
10
|
+
:description
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_loaded_associations
|
15
|
+
[ :scoring_parameters ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def allowed_order_columns
|
19
|
+
%w[id name created_at updated_at]
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_serializer_includes
|
23
|
+
{
|
24
|
+
index: [],
|
25
|
+
show: [ :scoring_parameters ],
|
26
|
+
create: [],
|
27
|
+
update: [ :scoring_parameters ]
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class ScoringParametersController < ApplicationController
|
3
3
|
include Dscf::Core::Common
|
4
|
+
include Dscf::Credit::Reviewable
|
4
5
|
|
5
6
|
def create
|
6
7
|
super do
|
7
8
|
scoring_parameter = @clazz.new(model_params)
|
8
9
|
scoring_parameter.created_by = current_user
|
9
|
-
scoring_parameter.
|
10
|
+
scoring_parameter.reviewed_by = current_user
|
10
11
|
|
11
12
|
scoring_parameter
|
12
13
|
end
|
@@ -20,30 +21,34 @@ module Dscf::Credit
|
|
20
21
|
:name,
|
21
22
|
:description,
|
22
23
|
:data_type,
|
23
|
-
:type,
|
24
24
|
:weight,
|
25
25
|
:min_value,
|
26
26
|
:max_value,
|
27
27
|
:active,
|
28
28
|
:previous_version_id,
|
29
|
-
:
|
29
|
+
:review_date,
|
30
|
+
:source,
|
31
|
+
:scoring_param_type_id,
|
32
|
+
:document_reference,
|
33
|
+
:status,
|
34
|
+
:review_feedback
|
30
35
|
)
|
31
36
|
end
|
32
37
|
|
33
38
|
def eager_loaded_associations
|
34
|
-
[ :bank, :created_by, :
|
39
|
+
[ :bank, :created_by, :reviewed_by, :scoring_param_type, :previous_version, :parameter_normalizers, :scoring_tables, :categories ]
|
35
40
|
end
|
36
41
|
|
37
42
|
def allowed_order_columns
|
38
|
-
%w[id name data_type
|
43
|
+
%w[id name data_type weight active review_date created_at updated_at]
|
39
44
|
end
|
40
45
|
|
41
46
|
def default_serializer_includes
|
42
47
|
{
|
43
48
|
index: [ :bank ],
|
44
|
-
show: [ :bank, :created_by, :
|
45
|
-
create: [ :bank, :created_by, :
|
46
|
-
update: [ :bank, :created_by, :
|
49
|
+
show: [ :bank, :created_by, :reviewed_by, :scoring_param_type, :previous_version, :parameter_normalizers, :scoring_tables, :categories ],
|
50
|
+
create: [ :bank, :created_by, :reviewed_by, :scoring_param_type ],
|
51
|
+
update: [ :bank, :created_by, :reviewed_by, :scoring_param_type, :parameter_normalizers, :scoring_tables, :categories ]
|
47
52
|
}
|
48
53
|
end
|
49
54
|
end
|
@@ -13,7 +13,7 @@ module Dscf::Credit
|
|
13
13
|
def activate
|
14
14
|
@obj = @clazz.find(params[:id])
|
15
15
|
if @obj.update(active: true)
|
16
|
-
render_success(data: @obj, serializer_options: { include: [ :
|
16
|
+
render_success(data: @obj, serializer_options: { include: [ :category, :scoring_parameter, :created_by ] })
|
17
17
|
else
|
18
18
|
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
19
19
|
end
|
@@ -24,7 +24,7 @@ module Dscf::Credit
|
|
24
24
|
def deactivate
|
25
25
|
@obj = @clazz.find(params[:id])
|
26
26
|
if @obj.update(active: false)
|
27
|
-
render_success(data: @obj, serializer_options: { include: [ :
|
27
|
+
render_success(data: @obj, serializer_options: { include: [ :category, :scoring_parameter, :created_by ] })
|
28
28
|
else
|
29
29
|
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
30
30
|
end
|
@@ -36,7 +36,7 @@ module Dscf::Credit
|
|
36
36
|
|
37
37
|
def model_params
|
38
38
|
params.require(:scoring_table).permit(
|
39
|
-
:
|
39
|
+
:category_id,
|
40
40
|
:scoring_parameter_id,
|
41
41
|
:weight,
|
42
42
|
:active
|
@@ -44,7 +44,7 @@ module Dscf::Credit
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def eager_loaded_associations
|
47
|
-
[ :
|
47
|
+
[ :category, :scoring_parameter, :created_by ]
|
48
48
|
end
|
49
49
|
|
50
50
|
def allowed_order_columns
|
@@ -53,10 +53,10 @@ module Dscf::Credit
|
|
53
53
|
|
54
54
|
def default_serializer_includes
|
55
55
|
{
|
56
|
-
index: [ :
|
57
|
-
show: [ :
|
58
|
-
create: [ :
|
59
|
-
update: [ :
|
56
|
+
index: [ :category, :scoring_parameter, :created_by ],
|
57
|
+
show: [ :category, :scoring_parameter, :created_by ],
|
58
|
+
create: [ :category, :scoring_parameter, :created_by ],
|
59
|
+
update: [ :category, :scoring_parameter, :created_by ]
|
60
60
|
}
|
61
61
|
end
|
62
62
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class SystemConfigsController < ApplicationController
|
3
3
|
include Dscf::Core::Common
|
4
|
+
include Dscf::Credit::Reviewable
|
4
5
|
|
5
6
|
def create
|
6
7
|
super do
|
7
8
|
obj = @clazz.new(model_params)
|
8
|
-
obj.
|
9
|
+
obj.reviewed_by = current_user
|
9
10
|
obj.last_updated_by = current_user
|
10
11
|
obj
|
11
12
|
end
|
@@ -25,24 +26,26 @@ module Dscf::Credit
|
|
25
26
|
params.require(:system_config).permit(
|
26
27
|
:config_definition_id,
|
27
28
|
:config_value,
|
28
|
-
:status
|
29
|
+
:status,
|
30
|
+
:review_date,
|
31
|
+
:review_feedback
|
29
32
|
)
|
30
33
|
end
|
31
34
|
|
32
35
|
def eager_loaded_associations
|
33
|
-
[ :config_definition, :last_updated_by, :
|
36
|
+
[ :config_definition, :last_updated_by, :reviewed_by ]
|
34
37
|
end
|
35
38
|
|
36
39
|
def allowed_order_columns
|
37
|
-
%w[id config_value status created_at updated_at]
|
40
|
+
%w[id config_value status review_date created_at updated_at]
|
38
41
|
end
|
39
42
|
|
40
43
|
def default_serializer_includes
|
41
44
|
{
|
42
45
|
index: [ :config_definition ],
|
43
|
-
show: [ :config_definition, :last_updated_by, :
|
44
|
-
create: [ :config_definition, :last_updated_by, :
|
45
|
-
update: [ :config_definition, :last_updated_by, :
|
46
|
+
show: [ :config_definition, :last_updated_by, :reviewed_by ],
|
47
|
+
create: [ :config_definition, :last_updated_by, :reviewed_by ],
|
48
|
+
update: [ :config_definition, :last_updated_by, :reviewed_by ]
|
46
49
|
}
|
47
50
|
end
|
48
51
|
end
|
@@ -4,6 +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 :loan_profiles, class_name: "Dscf::Credit::LoanProfile", foreign_key: "review_branch_id", dependent: :nullify
|
7
8
|
|
8
9
|
validates :branch_name, presence: true
|
9
10
|
validates :branch_name, uniqueness: { scope: :bank_id }
|
@@ -17,7 +18,7 @@ module Dscf::Credit
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.ransackable_associations(auth_object = nil)
|
20
|
-
%w[bank bank_staffs]
|
21
|
+
%w[bank bank_staffs loan_profiles]
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -4,6 +4,8 @@ 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 :scoring_tables, class_name: "Dscf::Credit::ScoringTable", foreign_key: "category_id", dependent: :destroy
|
8
|
+
has_many :scoring_parameters, through: :scoring_tables
|
7
9
|
|
8
10
|
validates :type, :name, presence: true
|
9
11
|
validates :name, uniqueness: { scope: :type }
|
@@ -11,11 +13,11 @@ module Dscf::Credit
|
|
11
13
|
scope :by_type, ->(category_type) { where(type: category_type) }
|
12
14
|
|
13
15
|
def self.ransackable_attributes(auth_object = nil)
|
14
|
-
%w[id type name description created_at updated_at]
|
16
|
+
%w[id type name description document_reference created_at updated_at]
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.ransackable_associations(auth_object = nil)
|
18
|
-
%w[credit_lines]
|
20
|
+
%w[credit_lines scoring_tables scoring_parameters]
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -5,26 +5,29 @@ module Dscf::Credit
|
|
5
5
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
6
|
belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
|
7
7
|
belongs_to :created_by, polymorphic: true
|
8
|
-
belongs_to :
|
8
|
+
belongs_to :reviewed_by, polymorphic: true, optional: true
|
9
|
+
|
9
10
|
has_many :credit_line_specs, class_name: "Dscf::Credit::CreditLineSpec", foreign_key: "credit_line_id", dependent: :destroy
|
10
11
|
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "credit_line_id", dependent: :destroy
|
11
|
-
has_many :
|
12
|
-
has_many :scoring_parameters, through: :
|
12
|
+
has_many :eligible_credit_lines, class_name: "Dscf::Credit::EligibleCreditLine", foreign_key: "credit_line_id", dependent: :destroy
|
13
|
+
has_many :scoring_parameters, through: :category, source: :scoring_parameters
|
13
14
|
|
14
15
|
validates :name, presence: true
|
15
16
|
validates :code, uniqueness: { scope: :bank_id }, allow_blank: true
|
16
|
-
validates :status, inclusion: { in: %w[pending approved active suspended] }
|
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
|
+
|
17
20
|
|
18
21
|
scope :active, -> { where(status: "active") }
|
19
22
|
scope :approved, -> { where(status: "approved") }
|
20
23
|
scope :pending, -> { where(status: "pending") }
|
21
24
|
|
22
25
|
def self.ransackable_attributes(auth_object = nil)
|
23
|
-
%w[id name code description status
|
26
|
+
%w[id name code description status review_date review_feedback document_reference created_at updated_at]
|
24
27
|
end
|
25
28
|
|
26
29
|
def self.ransackable_associations(auth_object = nil)
|
27
|
-
%w[bank category created_by
|
30
|
+
%w[bank category created_by reviewed_by credit_line_specs loans eligible_credit_lines scoring_parameters]
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -5,8 +5,8 @@ module Dscf::Credit
|
|
5
5
|
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
6
6
|
belongs_to :created_by, polymorphic: true
|
7
7
|
|
8
|
-
validates :min_amount, :max_amount, :interest_rate, :penalty_rate, :facilitation_fee_rate, :tax_rate, :max_penalty_days, :loan_duration, :interest_frequency, :interest_income_tax, :vat, :max_interest_calculation_days, :penalty_frequency, :penalty_income_tax, presence: true
|
9
|
-
validates :min_amount, :max_amount, numericality: { greater_than: 0 }
|
8
|
+
validates :min_amount, :max_amount, :interest_rate, :penalty_rate, :facilitation_fee_rate, :tax_rate, :credit_line_multiplier, :max_penalty_days, :loan_duration, :interest_frequency, :interest_income_tax, :vat, :max_interest_calculation_days, :penalty_frequency, :penalty_income_tax, presence: true
|
9
|
+
validates :min_amount, :max_amount, :credit_line_multiplier, numericality: { greater_than: 0 }
|
10
10
|
validates :interest_rate, :penalty_rate, :facilitation_fee_rate, :tax_rate, :interest_income_tax, :vat, :penalty_income_tax, numericality: { greater_than_or_equal_to: 0, less_than: 10 }
|
11
11
|
validates :max_penalty_days, :loan_duration, :max_interest_calculation_days, numericality: { greater_than: 0 }
|
12
12
|
validates :interest_frequency, inclusion: { in: %w[daily weekly monthly quarterly annually] }
|
@@ -19,7 +19,7 @@ module Dscf::Credit
|
|
19
19
|
scope :by_penalty_frequency, ->(frequency) { where(penalty_frequency: frequency) }
|
20
20
|
|
21
21
|
def self.ransackable_attributes(auth_object = nil)
|
22
|
-
%w[id min_amount max_amount interest_rate penalty_rate facilitation_fee_rate tax_rate max_penalty_days loan_duration interest_frequency interest_income_tax vat max_interest_calculation_days penalty_frequency penalty_income_tax active created_at updated_at]
|
22
|
+
%w[id min_amount max_amount interest_rate penalty_rate facilitation_fee_rate tax_rate credit_line_multiplier max_penalty_days loan_duration interest_frequency interest_income_tax vat max_interest_calculation_days penalty_frequency penalty_income_tax active created_at updated_at]
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.ransackable_associations(auth_object = nil)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class EligibleCreditLine < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_eligible_credit_lines"
|
4
|
+
|
5
|
+
belongs_to :loan_profile, class_name: "Dscf::Credit::LoanProfile", foreign_key: "loan_profile_id"
|
6
|
+
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
7
|
+
|
8
|
+
validates :credit_limit, presence: true
|
9
|
+
validates :credit_limit, numericality: { greater_than: 0 }
|
10
|
+
validates :available_limit, presence: true
|
11
|
+
validates :available_limit, numericality: { greater_than_or_equal_to: 0 }
|
12
|
+
validates :risk, numericality: { greater_than_or_equal_to: 0.01, less_than_or_equal_to: 0.9 }, allow_nil: true
|
13
|
+
|
14
|
+
scope :by_loan_profile, ->(loan_profile_id) { where(loan_profile_id: loan_profile_id) }
|
15
|
+
scope :by_credit_line, ->(credit_line_id) { where(credit_line_id: credit_line_id) }
|
16
|
+
scope :by_risk_range, ->(min, max) { where(risk: min..max) }
|
17
|
+
scope :by_credit_limit_range, ->(min, max) { where(credit_limit: min..max) }
|
18
|
+
scope :by_available_limit_range, ->(min, max) { where(available_limit: min..max) }
|
19
|
+
|
20
|
+
def self.ransackable_attributes(auth_object = nil)
|
21
|
+
%w[id credit_limit available_limit risk created_at updated_at]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.ransackable_associations(auth_object = nil)
|
25
|
+
%w[loan_profile credit_line]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -4,7 +4,7 @@ module Dscf::Credit
|
|
4
4
|
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
5
|
|
6
6
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
7
|
-
belongs_to :
|
7
|
+
belongs_to :kyc_reviewed_by, polymorphic: true
|
8
8
|
if defined?(Dscf::Core::User)
|
9
9
|
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
10
|
end
|
@@ -12,20 +12,21 @@ module Dscf::Credit
|
|
12
12
|
|
13
13
|
validates :name, :type, presence: true
|
14
14
|
validates :type, inclusion: { in: %w[individual corporate agent] }
|
15
|
-
validates :kyc_status, inclusion: { in: %w[pending approved rejected] }
|
16
15
|
validates :user_id, uniqueness: { scope: :bank_id }
|
17
16
|
validates :total_limit, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
18
17
|
|
18
|
+
enum :kyc_status, { pending: "pending", approved: "approved", rejected: "rejected" }
|
19
|
+
|
19
20
|
scope :approved, -> { where(kyc_status: "approved") }
|
20
21
|
scope :pending_kyc, -> { where(kyc_status: "pending") }
|
21
22
|
scope :rejected, -> { where(kyc_status: "rejected") }
|
22
23
|
|
23
24
|
def self.ransackable_attributes(auth_object = nil)
|
24
|
-
%w[id name type total_limit kyc_status created_at updated_at]
|
25
|
+
%w[id name type total_limit kyc_status kyc_review_date review_feedback created_at updated_at]
|
25
26
|
end
|
26
27
|
|
27
28
|
def self.ransackable_associations(auth_object = nil)
|
28
|
-
%w[bank user
|
29
|
+
%w[bank user kyc_reviewed_by facilitator_performances]
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -11,7 +11,6 @@ module Dscf::Credit
|
|
11
11
|
validates :score, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
12
12
|
|
13
13
|
scope :requiring_approval, -> { where(approval_required: true) }
|
14
|
-
scope :
|
15
|
-
scope :current, -> { where("expires_at IS NULL OR expires_at > ?", Time.current) }
|
14
|
+
scope :current, -> { where("created_at > ?", 30.days.ago) } # Assuming current means recent
|
16
15
|
end
|
17
16
|
end
|
@@ -3,21 +3,25 @@ module Dscf::Credit
|
|
3
3
|
self.table_name = "dscf_credit_loan_profiles"
|
4
4
|
|
5
5
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
|
-
belongs_to :
|
6
|
+
belongs_to :review_branch, class_name: "Dscf::Credit::BankBranch", foreign_key: "review_branch_id", optional: true
|
7
|
+
belongs_to :reviewed_by, polymorphic: true, optional: true
|
7
8
|
belongs_to :backer, polymorphic: true, optional: true
|
8
9
|
if defined?(Dscf::Core::User)
|
9
10
|
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
11
|
end
|
11
12
|
has_many :loan_profile_scoring_specs, class_name: "Dscf::Credit::LoanProfileScoringSpec", foreign_key: "loan_profile_id", dependent: :destroy
|
12
13
|
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "loan_profile_id", dependent: :destroy
|
14
|
+
has_many :eligible_credit_lines, class_name: "Dscf::Credit::EligibleCreditLine", foreign_key: "loan_profile_id", dependent: :destroy
|
13
15
|
|
14
|
-
validates :status, inclusion: { in: %w[pending approved rejected kyc_approved kyc_rejected] }
|
16
|
+
validates :status, inclusion: { in: %w[pending approved rejected manual_review kyc_approved kyc_rejected] }
|
17
|
+
enum :status, { pending: "pending", approved: "approved", rejected: "rejected", manual_review: "manual_review", kyc_approved: "kyc_approved", kyc_rejected: "kyc_rejected" }
|
15
18
|
validates :total_amount, :available_amount, numericality: { greater_than_or_equal_to: 0 }
|
16
19
|
validate :available_amount_not_greater_than_total_amount
|
17
20
|
|
18
21
|
scope :pending, -> { where(status: "pending") }
|
19
22
|
scope :approved, -> { where(status: "approved") }
|
20
23
|
scope :rejected, -> { where(status: "rejected") }
|
24
|
+
scope :manual_review, -> { where(status: "manual_review") }
|
21
25
|
scope :kyc_approved, -> { where(status: "kyc_approved") }
|
22
26
|
scope :kyc_rejected, -> { where(status: "kyc_rejected") }
|
23
27
|
scope :with_available_amount, -> { where("available_amount > 0") }
|
@@ -25,11 +29,11 @@ module Dscf::Credit
|
|
25
29
|
scope :by_available_amount_range, ->(min, max) { where(available_amount: min..max) }
|
26
30
|
|
27
31
|
def self.ransackable_attributes(auth_object = nil)
|
28
|
-
%w[id status total_amount available_amount
|
32
|
+
%w[id status total_amount available_amount review_feedback review_date created_at updated_at reviewed_by_type reviewed_by_id review_branch_id]
|
29
33
|
end
|
30
34
|
|
31
35
|
def self.ransackable_associations(auth_object = nil)
|
32
|
-
%w[bank user backer
|
36
|
+
%w[bank user backer reviewed_by review_branch loan_profile_scoring_specs loans eligible_credit_lines]
|
33
37
|
end
|
34
38
|
|
35
39
|
private
|
@@ -4,20 +4,18 @@ 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 :created_by, polymorphic: true
|
7
|
-
belongs_to :approved_by, polymorphic: true
|
8
7
|
|
9
|
-
validates :
|
10
|
-
validates :
|
8
|
+
validates :score, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
9
|
+
validates :total_limit, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
11
10
|
|
12
11
|
scope :active, -> { where(active: true) }
|
13
|
-
scope :expired, -> { where("expires_at < ?", Time.current) }
|
14
12
|
|
15
13
|
def self.ransackable_attributes(auth_object = nil)
|
16
|
-
%w[id score active
|
14
|
+
%w[id score total_limit active created_at updated_at]
|
17
15
|
end
|
18
16
|
|
19
17
|
def self.ransackable_associations(auth_object = nil)
|
20
|
-
%w[loan_profile created_by
|
18
|
+
%w[loan_profile created_by]
|
21
19
|
end
|
22
20
|
end
|
23
21
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringParamType < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_scoring_param_types"
|
4
|
+
|
5
|
+
has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "scoring_param_type_id", dependent: :restrict_with_error
|
6
|
+
|
7
|
+
validates :name, presence: true, uniqueness: true
|
8
|
+
|
9
|
+
def self.ransackable_attributes(auth_object = nil)
|
10
|
+
%w[id name description created_at updated_at]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.ransackable_associations(auth_object = nil)
|
14
|
+
%w[scoring_parameters]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,30 +1,31 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class ScoringParameter < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_scoring_parameters"
|
4
|
-
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
4
|
|
6
5
|
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
7
6
|
belongs_to :created_by, polymorphic: true
|
8
|
-
belongs_to :
|
7
|
+
belongs_to :reviewed_by, polymorphic: true
|
8
|
+
belongs_to :scoring_param_type, class_name: "Dscf::Credit::ScoringParamType", foreign_key: "scoring_param_type_id"
|
9
9
|
belongs_to :previous_version, class_name: "Dscf::Credit::ScoringParameter", optional: true
|
10
10
|
has_many :parameter_normalizers, class_name: "Dscf::Credit::ParameterNormalizer", foreign_key: "scoring_parameter_id", dependent: :destroy
|
11
11
|
has_many :scoring_tables, class_name: "Dscf::Credit::ScoringTable", foreign_key: "scoring_parameter_id", dependent: :destroy
|
12
|
-
has_many :
|
12
|
+
has_many :categories, through: :scoring_tables
|
13
13
|
|
14
|
-
validates :name, :data_type, :
|
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
|
-
validates :type, inclusion: { in: %w[income credit_history employment_status collateral] }
|
18
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" }
|
19
20
|
|
20
21
|
scope :active, -> { where(active: true) }
|
21
22
|
|
22
23
|
def self.ransackable_attributes(auth_object = nil)
|
23
|
-
%w[id name description data_type
|
24
|
+
%w[id name description data_type weight min_value max_value active status review_date review_feedback source document_reference created_at updated_at]
|
24
25
|
end
|
25
26
|
|
26
27
|
def self.ransackable_associations(auth_object = nil)
|
27
|
-
%w[bank created_by
|
28
|
+
%w[bank created_by reviewed_by scoring_param_type previous_version parameter_normalizers scoring_tables categories]
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -2,15 +2,15 @@ module Dscf::Credit
|
|
2
2
|
class ScoringTable < ApplicationRecord
|
3
3
|
self.table_name = "dscf_credit_scoring_tables"
|
4
4
|
|
5
|
-
belongs_to :
|
5
|
+
belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
|
6
6
|
belongs_to :scoring_parameter, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "scoring_parameter_id"
|
7
7
|
belongs_to :created_by, polymorphic: true
|
8
8
|
|
9
9
|
validates :weight, presence: true, numericality: { greater_than: 0, less_than_or_equal_to: 1 }
|
10
|
-
validates :
|
10
|
+
validates :category_id, uniqueness: { scope: :scoring_parameter_id }
|
11
11
|
|
12
12
|
scope :active, -> { where(active: true) }
|
13
|
-
scope :
|
13
|
+
scope :by_category, ->(category_id) { where(category_id: category_id) }
|
14
14
|
scope :by_scoring_parameter, ->(scoring_parameter_id) { where(scoring_parameter_id: scoring_parameter_id) }
|
15
15
|
|
16
16
|
def self.ransackable_attributes(auth_object = nil)
|
@@ -18,7 +18,7 @@ module Dscf::Credit
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.ransackable_associations(auth_object = nil)
|
21
|
-
%w[
|
21
|
+
%w[category scoring_parameter created_by]
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -4,10 +4,11 @@ module Dscf::Credit
|
|
4
4
|
|
5
5
|
belongs_to :config_definition, class_name: "Dscf::Credit::SystemConfigDefinition", foreign_key: "config_definition_id"
|
6
6
|
belongs_to :last_updated_by, polymorphic: true
|
7
|
-
belongs_to :
|
7
|
+
belongs_to :reviewed_by, polymorphic: true
|
8
8
|
|
9
9
|
validates :config_value, presence: true
|
10
|
-
validates :status, inclusion: { in: %w[pending approved rejected] }
|
10
|
+
validates :status, inclusion: { in: %w[pending approved rejected modify] }
|
11
|
+
enum :status, { pending: "pending", approved: "approved", rejected: "rejected", modify: "modify" }
|
11
12
|
validates :config_definition_id, uniqueness: true
|
12
13
|
|
13
14
|
scope :pending, -> { where(status: "pending") }
|
@@ -15,11 +16,11 @@ module Dscf::Credit
|
|
15
16
|
scope :rejected, -> { where(status: "rejected") }
|
16
17
|
|
17
18
|
def self.ransackable_attributes(auth_object = nil)
|
18
|
-
%w[id config_value status created_at updated_at]
|
19
|
+
%w[id config_value status review_date review_feedback created_at updated_at]
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.ransackable_associations(auth_object = nil)
|
22
|
-
%w[config_definition last_updated_by
|
23
|
+
%w[config_definition last_updated_by reviewed_by]
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class CategorySerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :type, :name, :description, :created_at, :updated_at
|
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
|
+
has_many :scoring_parameters, serializer: Dscf::Credit::ScoringParameterSerializer
|
6
8
|
end
|
7
9
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class CreditLineSerializer < ActiveModel::Serializer
|
3
|
-
attributes :id, :name, :code, :description, :status, :
|
3
|
+
attributes :id, :name, :code, :description, :status, :review_date, :review_feedback, :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 :
|
9
|
+
belongs_to :reviewed_by, serializer: Dscf::Core::UserSerializer
|
10
10
|
has_many :credit_line_specs, serializer: Dscf::Credit::CreditLineSpecSerializer
|
11
|
+
has_many :loans, serializer: Dscf::Credit::LoanSerializer
|
12
|
+
has_many :eligible_credit_lines, serializer: Dscf::Credit::EligibleCreditLineSerializer
|
11
13
|
end
|
12
14
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Dscf::Credit
|
2
2
|
class CreditLineSpecSerializer < ActiveModel::Serializer
|
3
3
|
attributes :id, :min_amount, :max_amount, :interest_rate, :penalty_rate,
|
4
|
-
:facilitation_fee_rate, :tax_rate, :max_penalty_days,
|
4
|
+
:facilitation_fee_rate, :tax_rate, :credit_line_multiplier, :max_penalty_days,
|
5
5
|
:loan_duration, :interest_frequency, :interest_income_tax,
|
6
6
|
:vat, :max_interest_calculation_days, :penalty_frequency,
|
7
7
|
:penalty_income_tax, :active, :created_at, :updated_at
|