dscf-credit 0.1.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/controllers/dscf/credit/application_controller.rb +8 -0
- data/app/controllers/dscf/credit/bank_branches_controller.rb +38 -0
- data/app/controllers/dscf/credit/bank_staffs_controller.rb +77 -0
- data/app/controllers/dscf/credit/banks_controller.rb +39 -0
- data/app/controllers/dscf/credit/categories_controller.rb +32 -0
- data/app/controllers/dscf/credit/credit_line_specs_controller.rb +72 -0
- data/app/controllers/dscf/credit/credit_lines_controller.rb +76 -0
- data/app/controllers/dscf/credit/facilitators_controller.rb +227 -0
- data/app/controllers/dscf/credit/loans_controller.rb +41 -0
- data/app/controllers/dscf/credit/parameter_normalizers_controller.rb +31 -0
- data/app/controllers/dscf/credit/payment_requests_controller.rb +38 -0
- data/app/controllers/dscf/credit/payments_controller.rb +36 -0
- data/app/controllers/dscf/credit/scoring_parameters_controller.rb +50 -0
- data/app/controllers/dscf/credit/scoring_tables_controller.rb +63 -0
- data/app/controllers/dscf/credit/system_config_definitions_controller.rb +34 -0
- data/app/controllers/dscf/credit/system_configs_controller.rb +49 -0
- data/app/controllers/dscf/credit/users_controller.rb +53 -0
- data/app/jobs/dscf/credit/application_job.rb +6 -0
- data/app/mailers/dscf/credit/application_mailer.rb +8 -0
- data/app/mailers/dscf/credit/bank_staff_welcome_mailer.rb +15 -0
- data/app/mailers/dscf/credit/facilitator_mailer.rb +54 -0
- data/app/models/dscf/credit/accounting_audit_request.rb +17 -0
- data/app/models/dscf/credit/accounting_entry.rb +15 -0
- data/app/models/dscf/credit/application_record.rb +7 -0
- data/app/models/dscf/credit/bank.rb +38 -0
- data/app/models/dscf/credit/bank_branch.rb +23 -0
- data/app/models/dscf/credit/bank_staff.rb +26 -0
- data/app/models/dscf/credit/category.rb +21 -0
- data/app/models/dscf/credit/credit_line.rb +30 -0
- data/app/models/dscf/credit/credit_line_spec.rb +37 -0
- data/app/models/dscf/credit/daily_routine_transaction.rb +18 -0
- data/app/models/dscf/credit/facilitator.rb +31 -0
- data/app/models/dscf/credit/facilitator_performance.rb +17 -0
- data/app/models/dscf/credit/failed_operations_log.rb +17 -0
- data/app/models/dscf/credit/loan.rb +33 -0
- data/app/models/dscf/credit/loan_profile.rb +43 -0
- data/app/models/dscf/credit/loan_profile_scoring_spec.rb +23 -0
- data/app/models/dscf/credit/loan_transaction.rb +17 -0
- data/app/models/dscf/credit/parameter_normalizer.rb +11 -0
- data/app/models/dscf/credit/payment.rb +22 -0
- data/app/models/dscf/credit/payment_request.rb +29 -0
- data/app/models/dscf/credit/scoring_parameter.rb +30 -0
- data/app/models/dscf/credit/scoring_table.rb +24 -0
- data/app/models/dscf/credit/system_config.rb +25 -0
- data/app/models/dscf/credit/system_config_definition.rb +25 -0
- data/app/serializers/dscf/core/business_serializer.rb +9 -0
- data/app/serializers/dscf/core/business_type_serializer.rb +7 -0
- data/app/serializers/dscf/core/role_serializer.rb +7 -0
- data/app/serializers/dscf/core/user_profile_serializer.rb +13 -0
- data/app/serializers/dscf/core/user_role_serializer.rb +16 -0
- data/app/serializers/dscf/core/user_serializer.rb +17 -0
- data/app/serializers/dscf/credit/bank_branch_serializer.rb +9 -0
- data/app/serializers/dscf/credit/bank_serializer.rb +9 -0
- data/app/serializers/dscf/credit/bank_staff_serializer.rb +8 -0
- data/app/serializers/dscf/credit/category_serializer.rb +7 -0
- data/app/serializers/dscf/credit/credit_line_serializer.rb +12 -0
- data/app/serializers/dscf/credit/credit_line_spec_serializer.rb +12 -0
- data/app/serializers/dscf/credit/parameter_normalizer_serializer.rb +8 -0
- data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +12 -0
- data/app/serializers/dscf/credit/scoring_table_serializer.rb +9 -0
- data/app/serializers/dscf/credit/system_config_definition_serializer.rb +9 -0
- data/app/serializers/dscf/credit/system_config_serializer.rb +18 -0
- data/app/services/dscf/credit/bank_staff_creation_service.rb +99 -0
- data/app/services/dscf/credit/facilitator_additional_info_service.rb +62 -0
- data/app/services/dscf/credit/facilitator_approval_service.rb +88 -0
- data/app/views/dscf/credit/bank_staff_welcome_mailer/welcome_email.html.erb +116 -0
- data/app/views/dscf/credit/bank_staff_welcome_mailer/welcome_email.text.erb +40 -0
- data/app/views/dscf/credit/facilitator_mailer/additional_info_received.html.erb +39 -0
- data/app/views/dscf/credit/facilitator_mailer/additional_info_received.text.erb +17 -0
- data/app/views/dscf/credit/facilitator_mailer/approval_notification.html.erb +59 -0
- data/app/views/dscf/credit/facilitator_mailer/approval_notification.text.erb +26 -0
- data/app/views/dscf/credit/facilitator_mailer/limit_update_notification.html.erb +39 -0
- data/app/views/dscf/credit/facilitator_mailer/limit_update_notification.text.erb +17 -0
- data/app/views/dscf/credit/facilitator_mailer/rejection_notification.html.erb +41 -0
- data/app/views/dscf/credit/facilitator_mailer/rejection_notification.text.erb +19 -0
- data/app/views/layouts/mailer.html.erb +125 -0
- data/app/views/layouts/mailer.text.erb +12 -0
- data/config/locales/en.yml +208 -0
- data/config/routes.rb +50 -0
- data/db/migrate/20250822091011_create_dscf_credit_categories.rb +15 -0
- data/db/migrate/20250822091015_create_dscf_credit_banks.rb +23 -0
- data/db/migrate/20250822091055_create_dscf_credit_bank_branches.rb +23 -0
- data/db/migrate/20250822091131_create_dscf_credit_credit_lines.rb +25 -0
- data/db/migrate/20250822091527_create_dscf_credit_credit_line_specs.rb +32 -0
- data/db/migrate/20250822091744_create_dscf_credit_system_config_definitions.rb +18 -0
- data/db/migrate/20250822091820_create_dscf_credit_system_configs.rb +17 -0
- data/db/migrate/20250822092050_create_dscf_credit_scoring_parameters.rb +30 -0
- data/db/migrate/20250822092225_create_dscf_credit_parameter_normalizers.rb +18 -0
- data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +25 -0
- data/db/migrate/20250822092417_create_dscf_credit_loan_profile_scoring_specs.rb +23 -0
- data/db/migrate/20250822092436_create_dscf_credit_facilitators.rb +22 -0
- data/db/migrate/20250822092528_create_dscf_credit_facilitator_performances.rb +26 -0
- data/db/migrate/20250822092608_create_dscf_credit_payment_requests.rb +26 -0
- data/db/migrate/20250822092654_create_dscf_credit_loans.rb +29 -0
- data/db/migrate/20250822092717_create_dscf_credit_loan_transactions.rb +21 -0
- data/db/migrate/20250822092738_create_dscf_credit_daily_routine_transactions.rb +23 -0
- data/db/migrate/20250822092819_create_dscf_credit_accounting_audit_requests.rb +20 -0
- data/db/migrate/20250822092843_create_dscf_credit_payments.rb +23 -0
- data/db/migrate/20250822092908_create_dscf_credit_failed_operations_logs.rb +21 -0
- data/db/migrate/20250822092936_create_dscf_credit_accounting_entries.rb +21 -0
- data/db/migrate/20250825231109_create_dscf_credit_bank_staff.rb +14 -0
- data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +18 -0
- data/db/seeds.rb +745 -0
- data/lib/dscf/credit/engine.rb +28 -0
- data/lib/dscf/credit/version.rb +5 -0
- data/lib/dscf/credit.rb +9 -0
- data/lib/tasks/dscf/credit_tasks.rake +4 -0
- data/spec/factories/dscf/credit/accounting_audit_requests.rb +58 -0
- data/spec/factories/dscf/credit/accounting_entries.rb +29 -0
- data/spec/factories/dscf/credit/bank_branches.rb +21 -0
- data/spec/factories/dscf/credit/bank_staffs.rb +19 -0
- data/spec/factories/dscf/credit/banks.rb +30 -0
- data/spec/factories/dscf/credit/categories.rb +27 -0
- data/spec/factories/dscf/credit/credit_line_specs.rb +57 -0
- data/spec/factories/dscf/credit/credit_lines.rb +32 -0
- data/spec/factories/dscf/credit/daily_routine_transactions.rb +36 -0
- data/spec/factories/dscf/credit/facilitator_performances.rb +30 -0
- data/spec/factories/dscf/credit/facilitators.rb +35 -0
- data/spec/factories/dscf/credit/failed_operations_logs.rb +34 -0
- data/spec/factories/dscf/credit/loan_profile_scoring_specs.rb +31 -0
- data/spec/factories/dscf/credit/loan_profiles.rb +49 -0
- data/spec/factories/dscf/credit/loan_transactions.rb +37 -0
- data/spec/factories/dscf/credit/loans.rb +37 -0
- data/spec/factories/dscf/credit/parameter_normalizers.rb +24 -0
- data/spec/factories/dscf/credit/payment_requests.rb +40 -0
- data/spec/factories/dscf/credit/payments.rb +39 -0
- data/spec/factories/dscf/credit/scoring_parameters.rb +48 -0
- data/spec/factories/dscf/credit/scoring_tables.rb +25 -0
- data/spec/factories/dscf/credit/system_config_definitions.rb +45 -0
- data/spec/factories/dscf/credit/system_configs.rb +29 -0
- metadata +456 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class DailyRoutineTransaction < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_daily_routine_transactions"
|
4
|
+
|
5
|
+
belongs_to :loan, class_name: "Dscf::Credit::Loan", foreign_key: "loan_id"
|
6
|
+
|
7
|
+
validates :routine_type, :amount, :status, presence: true
|
8
|
+
validates :amount, numericality: { greater_than: 0 }
|
9
|
+
validates :status, inclusion: { in: %w[pending processing completed failed] }
|
10
|
+
validates :routine_type, inclusion: {
|
11
|
+
in: %w[interest_calculation penalty_assessment payment_due_notification],
|
12
|
+
message: "%{value} is not a valid routine type"
|
13
|
+
}
|
14
|
+
|
15
|
+
scope :by_status, ->(status) { where(status: status) }
|
16
|
+
scope :by_routine_type, ->(type) { where(routine_type: type) }
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class Facilitator < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_facilitators"
|
4
|
+
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
|
+
|
6
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
7
|
+
belongs_to :kyc_approved_by, polymorphic: true
|
8
|
+
if defined?(Dscf::Core::User)
|
9
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
|
+
end
|
11
|
+
has_many :facilitator_performances, class_name: "Dscf::Credit::FacilitatorPerformance", foreign_key: "facilitator_id", dependent: :destroy
|
12
|
+
|
13
|
+
validates :name, :type, presence: true
|
14
|
+
validates :type, inclusion: { in: %w[individual corporate agent] }
|
15
|
+
validates :kyc_status, inclusion: { in: %w[pending approved rejected] }
|
16
|
+
validates :user_id, uniqueness: { scope: :bank_id }
|
17
|
+
validates :total_limit, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
18
|
+
|
19
|
+
scope :approved, -> { where(kyc_status: "approved") }
|
20
|
+
scope :pending_kyc, -> { where(kyc_status: "pending") }
|
21
|
+
scope :rejected, -> { where(kyc_status: "rejected") }
|
22
|
+
|
23
|
+
def self.ransackable_attributes(auth_object = nil)
|
24
|
+
%w[id name type total_limit kyc_status created_at updated_at]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.ransackable_associations(auth_object = nil)
|
28
|
+
%w[bank user kyc_approved_by facilitator_performances]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class FacilitatorPerformance < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_facilitator_performances"
|
4
|
+
|
5
|
+
belongs_to :facilitator, class_name: "Dscf::Credit::Facilitator", foreign_key: "facilitator_id"
|
6
|
+
belongs_to :created_by, polymorphic: true
|
7
|
+
|
8
|
+
validates :total_outstanding_loans, :total_outstanding_amount, presence: true
|
9
|
+
validates :total_outstanding_loans, numericality: { greater_than_or_equal_to: 0 }
|
10
|
+
validates :total_outstanding_amount, numericality: { greater_than_or_equal_to: 0 }
|
11
|
+
validates :score, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
12
|
+
|
13
|
+
scope :requiring_approval, -> { where(approval_required: true) }
|
14
|
+
scope :expired, -> { where("expires_at < ?", Time.current) }
|
15
|
+
scope :current, -> { where("expires_at IS NULL OR expires_at > ?", Time.current) }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class FailedOperationsLog < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_failed_operations_logs"
|
4
|
+
|
5
|
+
belongs_to :entity, polymorphic: true
|
6
|
+
|
7
|
+
validates :failure_type, :reason, presence: true
|
8
|
+
validates :failure_type, inclusion: {
|
9
|
+
in: %w[loan_disbursement payment_processing interest_calculation credit_scoring daily_routine accounting_entry]
|
10
|
+
}
|
11
|
+
validates :retry_count, numericality: { greater_than_or_equal_to: 0 }
|
12
|
+
|
13
|
+
scope :by_failure_type, ->(type) { where(failure_type: type) }
|
14
|
+
scope :resolved, -> { where(resolved: true) }
|
15
|
+
scope :unresolved, -> { where(resolved: false) }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class Loan < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_loans"
|
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
|
+
belongs_to :payment_request, class_name: "Dscf::Credit::PaymentRequest", foreign_key: "payment_request_id"
|
8
|
+
has_many :loan_transactions, class_name: "Dscf::Credit::LoanTransaction", foreign_key: "loan_id", dependent: :destroy
|
9
|
+
has_many :daily_routine_transactions, class_name: "Dscf::Credit::DailyRoutineTransaction", foreign_key: "loan_id", dependent: :destroy
|
10
|
+
|
11
|
+
validates :principal_amount, :total_loan_amount, :remaining_amount, :due_date, presence: true
|
12
|
+
validates :principal_amount, :total_loan_amount, :remaining_amount, numericality: { greater_than: 0 }
|
13
|
+
validates :accrued_interest, :accrued_penalty, :facilitation_fee, numericality: { greater_than_or_equal_to: 0 }
|
14
|
+
validates :status, inclusion: { in: %w[pending approved disbursed active overdue paid closed] }
|
15
|
+
|
16
|
+
scope :active, -> { where(status: "active") }
|
17
|
+
scope :overdue, -> { where(status: "overdue") }
|
18
|
+
scope :paid, -> { where(status: "paid") }
|
19
|
+
scope :due_today, -> { where(due_date: Date.current) }
|
20
|
+
scope :past_due, -> { where("due_date < ? AND status IN (?)", Date.current, [ "active", "overdue" ]) }
|
21
|
+
|
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]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ransackable_associations(auth_object = nil)
|
27
|
+
%w[loan_profile credit_line payment_request loan_transactions daily_routine_transactions]
|
28
|
+
end
|
29
|
+
|
30
|
+
delegate :user, to: :loan_profile, allow_nil: true
|
31
|
+
delegate :bank, to: :credit_line, allow_nil: true
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class LoanProfile < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_loan_profiles"
|
4
|
+
|
5
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
|
+
belongs_to :approved_by, polymorphic: true
|
7
|
+
belongs_to :backer, polymorphic: true, optional: true
|
8
|
+
if defined?(Dscf::Core::User)
|
9
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
10
|
+
end
|
11
|
+
has_many :loan_profile_scoring_specs, class_name: "Dscf::Credit::LoanProfileScoringSpec", foreign_key: "loan_profile_id", dependent: :destroy
|
12
|
+
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "loan_profile_id", dependent: :destroy
|
13
|
+
|
14
|
+
validates :status, inclusion: { in: %w[pending approved rejected kyc_approved kyc_rejected] }
|
15
|
+
validates :total_amount, :available_amount, numericality: { greater_than_or_equal_to: 0 }
|
16
|
+
validate :available_amount_not_greater_than_total_amount
|
17
|
+
|
18
|
+
scope :pending, -> { where(status: "pending") }
|
19
|
+
scope :approved, -> { where(status: "approved") }
|
20
|
+
scope :rejected, -> { where(status: "rejected") }
|
21
|
+
scope :kyc_approved, -> { where(status: "kyc_approved") }
|
22
|
+
scope :kyc_rejected, -> { where(status: "kyc_rejected") }
|
23
|
+
scope :with_available_amount, -> { where("available_amount > 0") }
|
24
|
+
scope :by_total_amount_range, ->(min, max) { where(total_amount: min..max) }
|
25
|
+
scope :by_available_amount_range, ->(min, max) { where(available_amount: min..max) }
|
26
|
+
|
27
|
+
def self.ransackable_attributes(auth_object = nil)
|
28
|
+
%w[id status total_amount available_amount rejection_reason created_at updated_at reviewed_by_type reviewed_by_id]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.ransackable_associations(auth_object = nil)
|
32
|
+
%w[bank user backer approved_by reviewed_by loan_profile_scoring_specs loans]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def available_amount_not_greater_than_total_amount
|
38
|
+
return unless total_amount && available_amount
|
39
|
+
|
40
|
+
errors.add(:available_amount, "cannot be greater than total amount") if available_amount > total_amount
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class LoanProfileScoringSpec < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_loan_profile_scoring_specs"
|
4
|
+
|
5
|
+
belongs_to :loan_profile, class_name: "Dscf::Credit::LoanProfile", foreign_key: "loan_profile_id"
|
6
|
+
belongs_to :created_by, polymorphic: true
|
7
|
+
belongs_to :approved_by, polymorphic: true
|
8
|
+
|
9
|
+
validates :scoring_input_data, :score, presence: true
|
10
|
+
validates :score, numericality: { greater_than_or_equal_to: 0 }
|
11
|
+
|
12
|
+
scope :active, -> { where(active: true) }
|
13
|
+
scope :expired, -> { where("expires_at < ?", Time.current) }
|
14
|
+
|
15
|
+
def self.ransackable_attributes(auth_object = nil)
|
16
|
+
%w[id score active expires_at created_at updated_at]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ransackable_associations(auth_object = nil)
|
20
|
+
%w[loan_profile created_by approved_by]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class LoanTransaction < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_loan_transactions"
|
4
|
+
|
5
|
+
belongs_to :loan, class_name: "Dscf::Credit::Loan", foreign_key: "loan_id"
|
6
|
+
|
7
|
+
validates :transaction_type, :amount, :transaction_reference, :status, presence: true
|
8
|
+
validates :amount, numericality: { greater_than: 0 }
|
9
|
+
validates :transaction_type, inclusion: { in: %w[disbursement repayment interest_accrual penalty fee_charge] }
|
10
|
+
validates :status, inclusion: { in: %w[pending processing completed failed reversed] }
|
11
|
+
validates :transaction_reference, uniqueness: true
|
12
|
+
|
13
|
+
scope :by_status, ->(status) { where(status: status) }
|
14
|
+
scope :disbursements, -> { where(transaction_type: "disbursement") }
|
15
|
+
scope :repayments, -> { where(transaction_type: "repayment") }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ParameterNormalizer < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_parameter_normalizers"
|
4
|
+
|
5
|
+
belongs_to :scoring_parameter, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "scoring_parameter_id"
|
6
|
+
|
7
|
+
validates :name, :raw_value, :normalized_value, presence: true
|
8
|
+
validates :raw_value, uniqueness: { scope: :scoring_parameter_id }
|
9
|
+
validates :normalized_value, numericality: { greater_than_or_equal_to: 0 }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class Payment < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_payments"
|
4
|
+
|
5
|
+
belongs_to :payment_request, class_name: "Dscf::Credit::PaymentRequest", foreign_key: "payment_request_id"
|
6
|
+
|
7
|
+
validates :amount, :receiver_account_reference, :transaction_reference, :status, presence: true
|
8
|
+
validates :amount, numericality: { greater_than: 0 }
|
9
|
+
validates :status, inclusion: { in: %w[pending processing completed failed cancelled] }
|
10
|
+
validates :transaction_reference, uniqueness: true
|
11
|
+
|
12
|
+
scope :by_status, ->(status) { where(status: status) }
|
13
|
+
|
14
|
+
def self.ransackable_attributes(auth_object = nil)
|
15
|
+
%w[id amount receiver_account_reference transaction_reference status failure_reason processed_at created_at updated_at]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.ransackable_associations(auth_object = nil)
|
19
|
+
%w[payment_request]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class PaymentRequest < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_payment_requests"
|
4
|
+
|
5
|
+
if defined?(Dscf::Core::User)
|
6
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
7
|
+
end
|
8
|
+
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "payment_request_id", dependent: :destroy
|
9
|
+
has_many :payments, class_name: "Dscf::Credit::Payment", foreign_key: "payment_request_id", dependent: :destroy
|
10
|
+
|
11
|
+
validates :order_id, presence: true, uniqueness: true
|
12
|
+
validates :request_type, :amount, :receiver_account_reference, presence: true
|
13
|
+
validates :amount, numericality: { greater_than: 0 }
|
14
|
+
validates :status, inclusion: { in: %w[pending approved rejected processed failed] }
|
15
|
+
|
16
|
+
scope :pending, -> { where(status: "pending") }
|
17
|
+
scope :approved, -> { where(status: "approved") }
|
18
|
+
scope :processed, -> { where(status: "processed") }
|
19
|
+
scope :failed, -> { where(status: "failed") }
|
20
|
+
|
21
|
+
def self.ransackable_attributes(auth_object = nil)
|
22
|
+
%w[id order_id request_type amount receiver_account_reference status failure_reason initiated_at approved_at created_at updated_at]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ransackable_associations(auth_object = nil)
|
26
|
+
%w[user loans payments]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringParameter < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_scoring_parameters"
|
4
|
+
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
|
+
|
6
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
7
|
+
belongs_to :created_by, polymorphic: true
|
8
|
+
belongs_to :approved_by, polymorphic: true
|
9
|
+
belongs_to :previous_version, class_name: "Dscf::Credit::ScoringParameter", optional: true
|
10
|
+
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 :credit_lines, through: :scoring_tables
|
13
|
+
|
14
|
+
validates :name, :data_type, :type, :weight, presence: true
|
15
|
+
validates :weight, numericality: { greater_than: 0, less_than_or_equal_to: 1 }
|
16
|
+
validates :data_type, inclusion: { in: %w[integer decimal boolean string] }
|
17
|
+
validates :type, inclusion: { in: %w[income credit_history employment_status collateral] }
|
18
|
+
validates :name, uniqueness: { scope: [ :bank_id, :active ] }
|
19
|
+
|
20
|
+
scope :active, -> { where(active: true) }
|
21
|
+
|
22
|
+
def self.ransackable_attributes(auth_object = nil)
|
23
|
+
%w[id name description data_type type weight min_value max_value active expires_at created_at updated_at]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ransackable_associations(auth_object = nil)
|
27
|
+
%w[bank created_by approved_by previous_version parameter_normalizers scoring_tables credit_lines]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringTable < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_scoring_tables"
|
4
|
+
|
5
|
+
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
6
|
+
belongs_to :scoring_parameter, class_name: "Dscf::Credit::ScoringParameter", foreign_key: "scoring_parameter_id"
|
7
|
+
belongs_to :created_by, polymorphic: true
|
8
|
+
|
9
|
+
validates :weight, presence: true, numericality: { greater_than: 0, less_than_or_equal_to: 1 }
|
10
|
+
validates :credit_line_id, uniqueness: { scope: :scoring_parameter_id }
|
11
|
+
|
12
|
+
scope :active, -> { where(active: true) }
|
13
|
+
scope :by_credit_line, ->(credit_line_id) { where(credit_line_id: credit_line_id) }
|
14
|
+
scope :by_scoring_parameter, ->(scoring_parameter_id) { where(scoring_parameter_id: scoring_parameter_id) }
|
15
|
+
|
16
|
+
def self.ransackable_attributes(auth_object = nil)
|
17
|
+
%w[id weight active created_at updated_at]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.ransackable_associations(auth_object = nil)
|
21
|
+
%w[credit_line scoring_parameter created_by]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfig < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_system_configs"
|
4
|
+
|
5
|
+
belongs_to :config_definition, class_name: "Dscf::Credit::SystemConfigDefinition", foreign_key: "config_definition_id"
|
6
|
+
belongs_to :last_updated_by, polymorphic: true
|
7
|
+
belongs_to :approved_by, polymorphic: true
|
8
|
+
|
9
|
+
validates :config_value, presence: true
|
10
|
+
validates :status, inclusion: { in: %w[pending approved rejected] }
|
11
|
+
validates :config_definition_id, uniqueness: true
|
12
|
+
|
13
|
+
scope :pending, -> { where(status: "pending") }
|
14
|
+
scope :approved, -> { where(status: "approved") }
|
15
|
+
scope :rejected, -> { where(status: "rejected") }
|
16
|
+
|
17
|
+
def self.ransackable_attributes(auth_object = nil)
|
18
|
+
%w[id config_value status created_at updated_at]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.ransackable_associations(auth_object = nil)
|
22
|
+
%w[config_definition last_updated_by approved_by]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfigDefinition < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_system_config_definitions"
|
4
|
+
|
5
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
|
+
has_one :system_config, class_name: "Dscf::Credit::SystemConfig", foreign_key: "config_definition_id", dependent: :destroy
|
7
|
+
|
8
|
+
validates :config_key, :value_type, presence: true
|
9
|
+
validates :config_key, uniqueness: { scope: :bank_id }
|
10
|
+
validates :value_type, inclusion: { in: %w[string integer decimal boolean json] }
|
11
|
+
validates :frequency, inclusion: { in: %w[once daily weekly monthly quarterly yearly] }, allow_blank: true
|
12
|
+
|
13
|
+
scope :by_frequency, ->(frequency) { where(frequency: frequency) }
|
14
|
+
scope :with_frequency, -> { where.not(frequency: [ nil, "" ]) }
|
15
|
+
scope :without_frequency, -> { where(frequency: [ nil, "" ]) }
|
16
|
+
|
17
|
+
def self.ransackable_attributes(auth_object = nil)
|
18
|
+
%w[id config_key description value_type frequency created_at updated_at]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.ransackable_associations(auth_object = nil)
|
22
|
+
%w[bank system_config]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dscf::Core
|
2
|
+
class BusinessSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :description, :contact_email, :contact_phone, :tin_number,
|
4
|
+
:created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :business_type, serializer: Dscf::Core::BusinessTypeSerializer
|
7
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Dscf::Core
|
2
|
+
class UserProfileSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :first_name, :middle_name, :last_name, :gender, :nationality,
|
4
|
+
:date_of_birth, :place_of_birth, :fayda_number, :occupation,
|
5
|
+
:position_title, :employer_name, :avg_monthly_income, :avg_annual_income,
|
6
|
+
:pep_status, :risk_score, :watchlist_hit, :verification_status,
|
7
|
+
:created_at, :updated_at
|
8
|
+
|
9
|
+
def full_name
|
10
|
+
[ object.first_name, object.middle_name, object.last_name ].compact.join(" ")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dscf::Core
|
2
|
+
class UserRoleSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :created_at, :updated_at
|
4
|
+
|
5
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
6
|
+
belongs_to :role, serializer: Dscf::Core::RoleSerializer
|
7
|
+
|
8
|
+
def role_code
|
9
|
+
object.role&.code
|
10
|
+
end
|
11
|
+
|
12
|
+
def role_name
|
13
|
+
object.role&.name
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Core
|
2
|
+
class UserSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :email, :phone, :verified_at, :temp_password, :created_at, :updated_at
|
4
|
+
|
5
|
+
has_one :user_profile, serializer: Dscf::Core::UserProfileSerializer
|
6
|
+
has_many :user_roles, serializer: Dscf::Core::UserRoleSerializer
|
7
|
+
has_many :businesses, serializer: Dscf::Core::BusinessSerializer
|
8
|
+
has_many :roles, serializer: Dscf::Core::RoleSerializer
|
9
|
+
|
10
|
+
|
11
|
+
def attributes(*args)
|
12
|
+
data = super
|
13
|
+
data.except!("password_digest")
|
14
|
+
data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankBranchSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :branch_name, :branch_code, :branch_address, :city, :country,
|
4
|
+
:contact_email, :contact_phone, :status, :created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
|
+
has_many :bank_staffs, serializer: Dscf::Credit::BankStaffSerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :registration_number, :swift_code, :headquarters_address,
|
4
|
+
:city, :country, :contact_email, :contact_phone, :status, :created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
7
|
+
has_many :bank_branches, serializer: Dscf::Credit::BankBranchSerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankStaffSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :status, :created_at, :updated_at
|
4
|
+
|
5
|
+
belongs_to :user, serializer: Dscf::Core::UserSerializer
|
6
|
+
belongs_to :bank_branch, serializer: Dscf::Credit::BankBranchSerializer
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class CreditLineSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :code, :description, :status, :approval_date,
|
4
|
+
:created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
|
+
belongs_to :category, serializer: Dscf::Credit::CategorySerializer
|
8
|
+
belongs_to :created_by, serializer: Dscf::Core::UserSerializer
|
9
|
+
belongs_to :approved_by, serializer: Dscf::Core::UserSerializer
|
10
|
+
has_many :credit_line_specs, serializer: Dscf::Credit::CreditLineSpecSerializer
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class CreditLineSpecSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :min_amount, :max_amount, :interest_rate, :penalty_rate,
|
4
|
+
:facilitation_fee_rate, :tax_rate, :max_penalty_days,
|
5
|
+
:loan_duration, :interest_frequency, :interest_income_tax,
|
6
|
+
:vat, :max_interest_calculation_days, :penalty_frequency,
|
7
|
+
:penalty_income_tax, :active, :created_at, :updated_at
|
8
|
+
|
9
|
+
belongs_to :credit_line, serializer: Dscf::Credit::CreditLineSerializer
|
10
|
+
belongs_to :created_by, serializer: Dscf::Core::UserSerializer
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ParameterNormalizerSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :description, :raw_value, :normalized_value,
|
4
|
+
:created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :scoring_parameter, serializer: Dscf::Credit::ScoringParameterSerializer
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringParameterSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :description, :data_type, :type, :weight, :min_value,
|
4
|
+
:max_value, :active, :expires_at, :created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
|
+
belongs_to :created_by, polymorphic: true
|
8
|
+
belongs_to :approved_by, polymorphic: true
|
9
|
+
belongs_to :previous_version, serializer: Dscf::Credit::ScoringParameterSerializer
|
10
|
+
has_many :parameter_normalizers, serializer: Dscf::Credit::ParameterNormalizerSerializer
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringTableSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :weight, :active, :created_at, :updated_at
|
4
|
+
|
5
|
+
belongs_to :credit_line, serializer: Dscf::Credit::CreditLineSerializer
|
6
|
+
belongs_to :scoring_parameter, serializer: Dscf::Credit::ScoringParameterSerializer
|
7
|
+
belongs_to :created_by, serializer: Dscf::Core::UserSerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfigDefinitionSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :config_key, :description, :value_type, :frequency,
|
4
|
+
:created_at, :updated_at
|
5
|
+
|
6
|
+
belongs_to :bank, serializer: Dscf::Credit::BankSerializer
|
7
|
+
has_one :system_config, serializer: Dscf::Credit::SystemConfigSerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfigSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :config_value, :status, :created_at, :updated_at
|
4
|
+
|
5
|
+
attribute :config_definition do
|
6
|
+
{
|
7
|
+
id: object.config_definition&.id,
|
8
|
+
config_key: object.config_definition&.config_key,
|
9
|
+
description: object.config_definition&.description,
|
10
|
+
value_type: object.config_definition&.value_type,
|
11
|
+
frequency: object.config_definition&.frequency
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
belongs_to :last_updated_by, serializer: Dscf::Core::UserSerializer
|
16
|
+
belongs_to :approved_by, serializer: Dscf::Core::UserSerializer
|
17
|
+
end
|
18
|
+
end
|