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,31 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ParameterNormalizersController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def model_params
|
8
|
+
params.require(:parameter_normalizer).permit(
|
9
|
+
:scoring_parameter_id,
|
10
|
+
:name,
|
11
|
+
:description,
|
12
|
+
:raw_value,
|
13
|
+
:normalized_value
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def eager_loaded_associations
|
18
|
+
[ :scoring_parameter ]
|
19
|
+
end
|
20
|
+
|
21
|
+
def allowed_order_columns
|
22
|
+
%w[id name raw_value normalized_value created_at updated_at]
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_serializer_includes
|
26
|
+
{
|
27
|
+
default: [ :scoring_parameter ]
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class PaymentRequestsController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def model_params
|
8
|
+
params.require(:payment_request).permit(
|
9
|
+
:user_id,
|
10
|
+
:order_id,
|
11
|
+
:request_type,
|
12
|
+
:amount,
|
13
|
+
:receiver_account_reference,
|
14
|
+
:status,
|
15
|
+
:failure_reason,
|
16
|
+
:initiated_at,
|
17
|
+
:approved_at
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def eager_loaded_associations
|
22
|
+
[ :user, :loans, :payments ]
|
23
|
+
end
|
24
|
+
|
25
|
+
def allowed_order_columns
|
26
|
+
%w[id order_id request_type amount status initiated_at approved_at created_at updated_at]
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_serializer_includes
|
30
|
+
{
|
31
|
+
index: [ :user ],
|
32
|
+
show: [ :user, :loans, :payments ],
|
33
|
+
create: [ :user ],
|
34
|
+
update: [ :user, :loans, :payments ]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class PaymentsController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def model_params
|
8
|
+
params.require(:payment).permit(
|
9
|
+
:payment_request_id,
|
10
|
+
:amount,
|
11
|
+
:receiver_account_reference,
|
12
|
+
:transaction_reference,
|
13
|
+
:status,
|
14
|
+
:failure_reason,
|
15
|
+
:processed_at
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def eager_loaded_associations
|
20
|
+
[ :payment_request ]
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowed_order_columns
|
24
|
+
%w[id amount status processed_at created_at updated_at]
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_serializer_includes
|
28
|
+
{
|
29
|
+
index: [ :payment_request ],
|
30
|
+
show: [ :payment_request ],
|
31
|
+
create: [ :payment_request ],
|
32
|
+
update: [ :payment_request ]
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringParametersController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
def create
|
6
|
+
super do
|
7
|
+
scoring_parameter = @clazz.new(model_params)
|
8
|
+
scoring_parameter.created_by = current_user
|
9
|
+
scoring_parameter.approved_by = current_user
|
10
|
+
|
11
|
+
scoring_parameter
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def model_params
|
18
|
+
params.require(:scoring_parameter).permit(
|
19
|
+
:bank_id,
|
20
|
+
:name,
|
21
|
+
:description,
|
22
|
+
:data_type,
|
23
|
+
:type,
|
24
|
+
:weight,
|
25
|
+
:min_value,
|
26
|
+
:max_value,
|
27
|
+
:active,
|
28
|
+
:previous_version_id,
|
29
|
+
:expires_at
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def eager_loaded_associations
|
34
|
+
[ :bank, :created_by, :approved_by, :previous_version, :parameter_normalizers ]
|
35
|
+
end
|
36
|
+
|
37
|
+
def allowed_order_columns
|
38
|
+
%w[id name data_type type weight active expires_at created_at updated_at]
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_serializer_includes
|
42
|
+
{
|
43
|
+
index: [ :bank ],
|
44
|
+
show: [ :bank, :created_by, :approved_by, :previous_version, :parameter_normalizers ],
|
45
|
+
create: [ :bank, :created_by, :approved_by ],
|
46
|
+
update: [ :bank, :created_by, :approved_by, :parameter_normalizers ]
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class ScoringTablesController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
def create
|
6
|
+
super do
|
7
|
+
scoring_table = @clazz.new(model_params)
|
8
|
+
scoring_table.created_by = current_user
|
9
|
+
scoring_table
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def activate
|
14
|
+
@obj = @clazz.find(params[:id])
|
15
|
+
if @obj.update(active: true)
|
16
|
+
render_success(data: @obj, serializer_options: { include: [ :credit_line, :scoring_parameter, :created_by ] })
|
17
|
+
else
|
18
|
+
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
19
|
+
end
|
20
|
+
rescue StandardError => e
|
21
|
+
render_error(error: e.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def deactivate
|
25
|
+
@obj = @clazz.find(params[:id])
|
26
|
+
if @obj.update(active: false)
|
27
|
+
render_success(data: @obj, serializer_options: { include: [ :credit_line, :scoring_parameter, :created_by ] })
|
28
|
+
else
|
29
|
+
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
30
|
+
end
|
31
|
+
rescue StandardError => e
|
32
|
+
render_error(error: e.message)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def model_params
|
38
|
+
params.require(:scoring_table).permit(
|
39
|
+
:credit_line_id,
|
40
|
+
:scoring_parameter_id,
|
41
|
+
:weight,
|
42
|
+
:active
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def eager_loaded_associations
|
47
|
+
[ :credit_line, :scoring_parameter, :created_by ]
|
48
|
+
end
|
49
|
+
|
50
|
+
def allowed_order_columns
|
51
|
+
%w[id weight active created_at updated_at]
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_serializer_includes
|
55
|
+
{
|
56
|
+
index: [ :credit_line, :scoring_parameter, :created_by ],
|
57
|
+
show: [ :credit_line, :scoring_parameter, :created_by ],
|
58
|
+
create: [ :credit_line, :scoring_parameter, :created_by ],
|
59
|
+
update: [ :credit_line, :scoring_parameter, :created_by ]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfigDefinitionsController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def model_params
|
8
|
+
params.require(:system_config_definition).permit(
|
9
|
+
:bank_id,
|
10
|
+
:config_key,
|
11
|
+
:description,
|
12
|
+
:value_type,
|
13
|
+
:frequency
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def eager_loaded_associations
|
18
|
+
[ :bank, :system_config ]
|
19
|
+
end
|
20
|
+
|
21
|
+
def allowed_order_columns
|
22
|
+
%w[id config_key description value_type frequency created_at updated_at]
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_serializer_includes
|
26
|
+
{
|
27
|
+
index: [ :bank ],
|
28
|
+
show: [ :bank, :system_config ],
|
29
|
+
create: [ :bank ],
|
30
|
+
update: [ :bank, :system_config ]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class SystemConfigsController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
def create
|
6
|
+
super do
|
7
|
+
obj = @clazz.new(model_params)
|
8
|
+
obj.approved_by = current_user
|
9
|
+
obj.last_updated_by = current_user
|
10
|
+
obj
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
super do
|
16
|
+
obj = set_object
|
17
|
+
obj.last_updated_by = current_user
|
18
|
+
obj
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def model_params
|
25
|
+
params.require(:system_config).permit(
|
26
|
+
:config_definition_id,
|
27
|
+
:config_value,
|
28
|
+
:status
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def eager_loaded_associations
|
33
|
+
[ :config_definition, :last_updated_by, :approved_by ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def allowed_order_columns
|
37
|
+
%w[id config_value status created_at updated_at]
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_serializer_includes
|
41
|
+
{
|
42
|
+
index: [ :config_definition ],
|
43
|
+
show: [ :config_definition, :last_updated_by, :approved_by ],
|
44
|
+
create: [ :config_definition, :last_updated_by, :approved_by ],
|
45
|
+
update: [ :config_definition, :last_updated_by, :approved_by ]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class UsersController < ApplicationController
|
3
|
+
include Dscf::Core::Common
|
4
|
+
|
5
|
+
def index
|
6
|
+
super do
|
7
|
+
if params[:business_type].present?
|
8
|
+
business_type_name = params[:business_type].downcase
|
9
|
+
|
10
|
+
business_type = Dscf::Core::BusinessType.find_by(name: business_type_name)
|
11
|
+
unless business_type
|
12
|
+
return render_error(
|
13
|
+
"validation.invalid",
|
14
|
+
errors: "Invalid business type: #{params[:business_type]}",
|
15
|
+
status: :not_found
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
@clazz.joins(businesses: :business_type)
|
20
|
+
.where(dscf_core_business_types: { name: business_type_name })
|
21
|
+
.distinct
|
22
|
+
else
|
23
|
+
@clazz.all
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def model_params
|
31
|
+
params.require(:user).permit(
|
32
|
+
:email,
|
33
|
+
:phone,
|
34
|
+
:verified_at,
|
35
|
+
:temp_password
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def eager_loaded_associations
|
40
|
+
[ :user_profile, :businesses, :user_roles, businesses: :business_type ]
|
41
|
+
end
|
42
|
+
|
43
|
+
def allowed_order_columns
|
44
|
+
%w[id email phone verified_at created_at updated_at]
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_serializer_includes
|
48
|
+
{
|
49
|
+
default: [ :user_profile, :businesses, :user_roles, "businesses.business_type" ]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankStaffWelcomeMailer < ApplicationMailer
|
3
|
+
def welcome_email(user, generated_password, bank_staff = nil)
|
4
|
+
@user = user
|
5
|
+
@generated_password = generated_password
|
6
|
+
@bank_staff = bank_staff
|
7
|
+
@login_url = ENV["FRONTEND_BASE_URL"] || "http://localhost:3000"
|
8
|
+
|
9
|
+
mail(
|
10
|
+
to: user.email,
|
11
|
+
subject: "Welcome to DSCF Banking System - Your Account Details"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class FacilitatorMailer < ApplicationMailer
|
3
|
+
def approval_notification(facilitator, additional_info_token)
|
4
|
+
@facilitator = facilitator
|
5
|
+
@merchant = facilitator.user
|
6
|
+
@additional_info_url = generate_additional_info_url(additional_info_token)
|
7
|
+
@total_limit = facilitator.total_limit
|
8
|
+
|
9
|
+
mail(
|
10
|
+
to: @merchant.email,
|
11
|
+
subject: "Facilitator Application Approved - Submit Additional Information"
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def rejection_notification(facilitator, rejection_reason = nil)
|
16
|
+
@facilitator = facilitator
|
17
|
+
@merchant = facilitator.user
|
18
|
+
@rejection_reason = rejection_reason
|
19
|
+
|
20
|
+
mail(
|
21
|
+
to: @merchant.email,
|
22
|
+
subject: "Facilitator Application Update"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def limit_update_notification(facilitator)
|
27
|
+
@facilitator = facilitator
|
28
|
+
@merchant = facilitator.user
|
29
|
+
@total_limit = facilitator.total_limit
|
30
|
+
|
31
|
+
mail(
|
32
|
+
to: @merchant.email,
|
33
|
+
subject: "Facilitator Limit Updated"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def additional_info_received(facilitator)
|
38
|
+
@facilitator = facilitator
|
39
|
+
@merchant = facilitator.user
|
40
|
+
|
41
|
+
mail(
|
42
|
+
to: @merchant.email,
|
43
|
+
subject: "Additional Information Received"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def generate_additional_info_url(token)
|
50
|
+
frontend_base_url = ENV["FRONTEND_BASE_URL"] || "https://test-frontend.com"
|
51
|
+
"#{frontend_base_url}/facilitator/additional-info?token=#{token}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class AccountingAuditRequest < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_accounting_audit_requests"
|
4
|
+
|
5
|
+
belongs_to :source_entity, polymorphic: true
|
6
|
+
|
7
|
+
validates :transaction_type, :amount, :webhook_key, :status, presence: true
|
8
|
+
validates :transaction_type, inclusion: { in: %w[debit credit transfer adjustment] }
|
9
|
+
validates :status, inclusion: { in: %w[pending processing completed failed] }
|
10
|
+
validates :amount, numericality: { greater_than: 0 }
|
11
|
+
validates :webhook_key, uniqueness: true
|
12
|
+
|
13
|
+
scope :by_status, ->(status) { where(status: status) }
|
14
|
+
scope :by_transaction_type, ->(type) { where(transaction_type: type) }
|
15
|
+
scope :by_amount_range, ->(min, max) { where(amount: min..max) }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class AccountingEntry < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_accounting_entries"
|
4
|
+
|
5
|
+
belongs_to :audit_request, class_name: "Dscf::Credit::AccountingAuditRequest", foreign_key: "audit_request_id"
|
6
|
+
|
7
|
+
validates :account_code, :entry_type, :amount, :status, presence: true
|
8
|
+
validates :amount, numericality: { greater_than: 0 }
|
9
|
+
validates :entry_type, inclusion: { in: %w[debit credit] }
|
10
|
+
validates :status, inclusion: { in: %w[pending completed failed] }
|
11
|
+
|
12
|
+
scope :by_entry_type, ->(type) { where(entry_type: type) }
|
13
|
+
scope :by_status, ->(status) { where(status: status) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class Bank < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_banks"
|
4
|
+
|
5
|
+
if defined?(Dscf::Core::User)
|
6
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id", optional: true
|
7
|
+
end
|
8
|
+
has_many :bank_branches, class_name: "Dscf::Credit::BankBranch",
|
9
|
+
foreign_key: "bank_id", dependent: :destroy
|
10
|
+
has_many :credit_lines, class_name: "Dscf::Credit::CreditLine",
|
11
|
+
foreign_key: "bank_id", dependent: :destroy
|
12
|
+
has_many :system_config_definitions, class_name: "Dscf::Credit::SystemConfigDefinition",
|
13
|
+
foreign_key: "bank_id", dependent: :destroy
|
14
|
+
has_many :scoring_parameters, class_name: "Dscf::Credit::ScoringParameter",
|
15
|
+
foreign_key: "bank_id", dependent: :destroy
|
16
|
+
has_many :loan_profiles, class_name: "Dscf::Credit::LoanProfile",
|
17
|
+
foreign_key: "bank_id", dependent: :destroy
|
18
|
+
has_many :facilitators, class_name: "Dscf::Credit::Facilitator",
|
19
|
+
foreign_key: "bank_id", dependent: :destroy
|
20
|
+
has_many :bank_staffs, through: :bank_branches, class_name: "Dscf::Credit::BankStaff"
|
21
|
+
|
22
|
+
validates :name, presence: true
|
23
|
+
validates :registration_number, uniqueness: true, allow_blank: true
|
24
|
+
validates :swift_code, uniqueness: true, allow_blank: true
|
25
|
+
validates :status, inclusion: { in: %w[active inactive suspended] }
|
26
|
+
|
27
|
+
scope :active, -> { where(status: "active") }
|
28
|
+
scope :inactive, -> { where(status: "inactive") }
|
29
|
+
|
30
|
+
def self.ransackable_attributes(auth_object = nil)
|
31
|
+
%w[id name registration_number swift_code headquarters_address city country contact_email contact_phone status created_at updated_at]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.ransackable_associations(auth_object = nil)
|
35
|
+
%w[user bank_branches credit_lines system_config_definitions scoring_parameters loan_profiles facilitators bank_staffs]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankBranch < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_bank_branches"
|
4
|
+
|
5
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
|
+
has_many :bank_staffs, class_name: "Dscf::Credit::BankStaff", foreign_key: "bank_branch_id", dependent: :destroy
|
7
|
+
|
8
|
+
validates :branch_name, presence: true
|
9
|
+
validates :branch_name, uniqueness: { scope: :bank_id }
|
10
|
+
validates :branch_code, uniqueness: { scope: :bank_id }, allow_blank: true
|
11
|
+
validates :status, inclusion: { in: %w[active inactive] }
|
12
|
+
|
13
|
+
scope :active, -> { where(status: "active") }
|
14
|
+
|
15
|
+
def self.ransackable_attributes(auth_object = nil)
|
16
|
+
%w[id branch_name branch_code branch_address city country contact_email contact_phone status created_at updated_at]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ransackable_associations(auth_object = nil)
|
20
|
+
%w[bank bank_staffs]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class BankStaff < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_bank_staffs"
|
4
|
+
|
5
|
+
if defined?(Dscf::Core::User)
|
6
|
+
belongs_to :user, class_name: "Dscf::Core::User", foreign_key: "user_id"
|
7
|
+
end
|
8
|
+
belongs_to :bank_branch, class_name: "Dscf::Credit::BankBranch", foreign_key: "bank_branch_id"
|
9
|
+
|
10
|
+
validates :status, inclusion: { in: %w[active inactive terminated] }
|
11
|
+
validates :user_id, uniqueness: { scope: :bank_branch_id }
|
12
|
+
|
13
|
+
scope :active, -> { where(status: "active") }
|
14
|
+
scope :inactive, -> { where(status: "inactive") }
|
15
|
+
|
16
|
+
def self.ransackable_attributes(auth_object = nil)
|
17
|
+
%w[id status created_at updated_at]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.ransackable_associations(auth_object = nil)
|
21
|
+
%w[user bank_branch]
|
22
|
+
end
|
23
|
+
|
24
|
+
delegate :bank, to: :bank_branch, allow_nil: true
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class Category < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_categories"
|
4
|
+
self.inheritance_column = nil # Disable STI since 'type' is a business attribute
|
5
|
+
|
6
|
+
has_many :credit_lines, class_name: "Dscf::Credit::CreditLine", foreign_key: "category_id", dependent: :nullify
|
7
|
+
|
8
|
+
validates :type, :name, presence: true
|
9
|
+
validates :name, uniqueness: { scope: :type }
|
10
|
+
|
11
|
+
scope :by_type, ->(category_type) { where(type: category_type) }
|
12
|
+
|
13
|
+
def self.ransackable_attributes(auth_object = nil)
|
14
|
+
%w[id type name description created_at updated_at]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.ransackable_associations(auth_object = nil)
|
18
|
+
%w[credit_lines]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class CreditLine < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_credit_lines"
|
4
|
+
|
5
|
+
belongs_to :bank, class_name: "Dscf::Credit::Bank", foreign_key: "bank_id"
|
6
|
+
belongs_to :category, class_name: "Dscf::Credit::Category", foreign_key: "category_id"
|
7
|
+
belongs_to :created_by, polymorphic: true
|
8
|
+
belongs_to :approved_by, polymorphic: true, optional: true
|
9
|
+
has_many :credit_line_specs, class_name: "Dscf::Credit::CreditLineSpec", foreign_key: "credit_line_id", dependent: :destroy
|
10
|
+
has_many :loans, class_name: "Dscf::Credit::Loan", foreign_key: "credit_line_id", dependent: :destroy
|
11
|
+
has_many :scoring_tables, class_name: "Dscf::Credit::ScoringTable", foreign_key: "credit_line_id", dependent: :destroy
|
12
|
+
has_many :scoring_parameters, through: :scoring_tables
|
13
|
+
|
14
|
+
validates :name, presence: true
|
15
|
+
validates :code, uniqueness: { scope: :bank_id }, allow_blank: true
|
16
|
+
validates :status, inclusion: { in: %w[pending approved active suspended] }
|
17
|
+
|
18
|
+
scope :active, -> { where(status: "active") }
|
19
|
+
scope :approved, -> { where(status: "approved") }
|
20
|
+
scope :pending, -> { where(status: "pending") }
|
21
|
+
|
22
|
+
def self.ransackable_attributes(auth_object = nil)
|
23
|
+
%w[id name code description status approval_date created_at updated_at]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ransackable_associations(auth_object = nil)
|
27
|
+
%w[bank category created_by approved_by credit_line_specs loans scoring_tables scoring_parameters]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Dscf::Credit
|
2
|
+
class CreditLineSpec < ApplicationRecord
|
3
|
+
self.table_name = "dscf_credit_credit_line_specs"
|
4
|
+
|
5
|
+
belongs_to :credit_line, class_name: "Dscf::Credit::CreditLine", foreign_key: "credit_line_id"
|
6
|
+
belongs_to :created_by, polymorphic: true
|
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 }
|
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
|
+
validates :max_penalty_days, :loan_duration, :max_interest_calculation_days, numericality: { greater_than: 0 }
|
12
|
+
validates :interest_frequency, inclusion: { in: %w[daily weekly monthly quarterly annually] }
|
13
|
+
validates :penalty_frequency, inclusion: { in: %w[daily weekly monthly] }
|
14
|
+
validate :max_amount_greater_than_min_amount
|
15
|
+
|
16
|
+
scope :active, -> { where(active: true) }
|
17
|
+
scope :by_duration, ->(duration) { where(loan_duration: duration) }
|
18
|
+
scope :by_interest_frequency, ->(frequency) { where(interest_frequency: frequency) }
|
19
|
+
scope :by_penalty_frequency, ->(frequency) { where(penalty_frequency: frequency) }
|
20
|
+
|
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]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ransackable_associations(auth_object = nil)
|
26
|
+
%w[credit_line created_by]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def max_amount_greater_than_min_amount
|
32
|
+
return unless min_amount && max_amount
|
33
|
+
|
34
|
+
errors.add(:max_amount, "must be greater than minimum amount") if max_amount <= min_amount
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|