dscf-credit 0.1.2 → 0.1.4

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/dscf/core/authenticatable.rb +81 -0
  3. data/app/controllers/concerns/dscf/core/common.rb +200 -0
  4. data/app/controllers/concerns/dscf/core/filterable.rb +12 -0
  5. data/app/controllers/concerns/dscf/core/json_response.rb +77 -0
  6. data/app/controllers/concerns/dscf/core/pagination.rb +71 -0
  7. data/app/controllers/concerns/dscf/core/token_authenticatable.rb +53 -0
  8. data/app/controllers/dscf/credit/categories_controller.rb +3 -3
  9. data/app/controllers/dscf/credit/credit_limit_calculations_controller.rb +50 -0
  10. data/app/controllers/dscf/credit/credit_line_specs_controller.rb +2 -1
  11. data/app/controllers/dscf/credit/credit_lines_controller.rb +3 -3
  12. data/app/controllers/dscf/credit/disbursements_controller.rb +55 -0
  13. data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +50 -0
  14. data/app/controllers/dscf/credit/facilitators_controller.rb +2 -1
  15. data/app/controllers/dscf/credit/loan_profiles_controller.rb +138 -0
  16. data/app/controllers/dscf/credit/payment_requests_controller.rb +54 -5
  17. data/app/controllers/dscf/credit/repayments_controller.rb +53 -0
  18. data/app/controllers/dscf/credit/scoring_parameters_controller.rb +3 -3
  19. data/app/controllers/dscf/credit/scoring_tables_controller.rb +8 -8
  20. data/app/controllers/dscf/credit/users_controller.rb +18 -0
  21. data/app/models/dscf/credit/bank_branch.rb +2 -1
  22. data/app/models/dscf/credit/category.rb +3 -1
  23. data/app/models/dscf/credit/credit_line.rb +3 -3
  24. data/app/models/dscf/credit/credit_line_spec.rb +3 -3
  25. data/app/models/dscf/credit/eligible_credit_line.rb +28 -0
  26. data/app/models/dscf/credit/loan_profile.rb +8 -5
  27. data/app/models/dscf/credit/loan_profile_scoring_spec.rb +4 -5
  28. data/app/models/dscf/credit/scoring_parameter.rb +2 -2
  29. data/app/models/dscf/credit/scoring_table.rb +4 -4
  30. data/app/serializers/dscf/credit/bank_branch_serializer.rb +1 -0
  31. data/app/serializers/dscf/credit/category_serializer.rb +2 -0
  32. data/app/serializers/dscf/credit/credit_line_serializer.rb +2 -0
  33. data/app/serializers/dscf/credit/credit_line_spec_serializer.rb +1 -1
  34. data/app/serializers/dscf/credit/daily_routine_transaction_serializer.rb +8 -0
  35. data/app/serializers/dscf/credit/eligible_credit_line_serializer.rb +8 -0
  36. data/app/serializers/dscf/credit/loan_profile_scoring_spec_serializer.rb +8 -0
  37. data/app/serializers/dscf/credit/loan_profile_serializer.rb +15 -0
  38. data/app/serializers/dscf/credit/loan_serializer.rb +12 -0
  39. data/app/serializers/dscf/credit/loan_transaction_serializer.rb +8 -0
  40. data/app/serializers/dscf/credit/payment_request_serializer.rb +10 -0
  41. data/app/serializers/dscf/credit/payment_serializer.rb +8 -0
  42. data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +2 -0
  43. data/app/serializers/dscf/credit/scoring_table_serializer.rb +1 -1
  44. data/app/services/dscf/credit/credit_limit_calculation_service.rb +153 -0
  45. data/app/services/dscf/credit/disbursement_service.rb +180 -0
  46. data/app/services/dscf/credit/facilitator_approval_service.rb +3 -4
  47. data/app/services/dscf/credit/repayment_service.rb +216 -0
  48. data/app/services/dscf/credit/risk_application_service.rb +27 -0
  49. data/app/services/dscf/credit/scoring_service.rb +297 -0
  50. data/config/locales/en.yml +91 -0
  51. data/config/routes.rb +19 -7
  52. data/db/migrate/20250822091527_create_dscf_credit_credit_line_specs.rb +1 -0
  53. data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +2 -1
  54. data/db/migrate/20250822092417_create_dscf_credit_loan_profile_scoring_specs.rb +5 -8
  55. data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +2 -2
  56. data/db/migrate/20250917120000_create_dscf_credit_eligible_credit_lines.rb +18 -0
  57. data/db/seeds.rb +88 -22
  58. data/lib/dscf/credit/version.rb +1 -1
  59. data/spec/factories/dscf/credit/credit_line_specs.rb +1 -0
  60. data/spec/factories/dscf/credit/credit_lines.rb +3 -3
  61. data/spec/factories/dscf/credit/eligible_credit_lines.rb +33 -0
  62. data/spec/factories/dscf/credit/loan_profile_scoring_specs.rb +1 -4
  63. data/spec/factories/dscf/credit/loan_profiles.rb +1 -0
  64. data/spec/factories/dscf/credit/scoring_tables.rb +1 -1
  65. metadata +29 -2
@@ -3,5 +3,7 @@ module Dscf::Credit
3
3
  attributes :id, :type, :name, :description, :document_reference, :created_at, :updated_at
4
4
 
5
5
  has_many :credit_lines, serializer: Dscf::Credit::CreditLineSerializer
6
+ has_many :scoring_tables, serializer: Dscf::Credit::ScoringTableSerializer
7
+ has_many :scoring_parameters, serializer: Dscf::Credit::ScoringParameterSerializer
6
8
  end
7
9
  end
@@ -8,5 +8,7 @@ module Dscf::Credit
8
8
  belongs_to :created_by, serializer: Dscf::Core::UserSerializer
9
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
@@ -0,0 +1,8 @@
1
+ module Dscf::Credit
2
+ class DailyRoutineTransactionSerializer < ActiveModel::Serializer
3
+ attributes :id, :routine_type, :amount, :status, :processed_at,
4
+ :failure_reason, :created_at, :updated_at
5
+
6
+ belongs_to :loan, serializer: LoanSerializer
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Dscf::Credit
2
+ class EligibleCreditLineSerializer < ActiveModel::Serializer
3
+ attributes :id, :credit_limit, :available_limit, :risk, :created_at, :updated_at
4
+
5
+ belongs_to :loan_profile, serializer: Dscf::Credit::LoanProfileSerializer
6
+ belongs_to :credit_line, serializer: Dscf::Credit::CreditLineSerializer
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Dscf::Credit
2
+ class LoanProfileScoringSpecSerializer < ActiveModel::Serializer
3
+ attributes :id, :scoring_input_data, :score, :total_limit, :active, :created_at, :updated_at
4
+
5
+ belongs_to :loan_profile, serializer: Dscf::Credit::LoanProfileSerializer
6
+ belongs_to :created_by
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ module Dscf::Credit
2
+ class LoanProfileSerializer < ActiveModel::Serializer
3
+ attributes :id, :status, :total_amount, :available_amount, :review_date, :review_feedback, :created_at, :updated_at
4
+
5
+ belongs_to :bank, serializer: Dscf::Credit::BankSerializer
6
+ belongs_to :review_branch, serializer: Dscf::Credit::BankBranchSerializer
7
+ belongs_to :reviewed_by
8
+ belongs_to :backer
9
+ belongs_to :user, serializer: Dscf::Core::UserSerializer
10
+
11
+ has_many :loan_profile_scoring_specs, serializer: Dscf::Credit::LoanProfileScoringSpecSerializer
12
+ has_many :loans, serializer: Dscf::Credit::LoanSerializer
13
+ has_many :eligible_credit_lines, serializer: Dscf::Credit::EligibleCreditLineSerializer
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module Dscf::Credit
2
+ class LoanSerializer < ActiveModel::Serializer
3
+ attributes :id, :status, :principal_amount, :accrued_interest, :accrued_penalty, :facilitation_fee,
4
+ :total_loan_amount, :remaining_amount, :due_date, :disbursed_at, :created_at, :updated_at
5
+
6
+ belongs_to :loan_profile, serializer: LoanProfileSerializer
7
+ belongs_to :credit_line, serializer: CreditLineSerializer
8
+ belongs_to :payment_request, serializer: PaymentRequestSerializer
9
+ has_many :loan_transactions, serializer: LoanTransactionSerializer
10
+ has_many :daily_routine_transactions, serializer: DailyRoutineTransactionSerializer
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Dscf::Credit
2
+ class LoanTransactionSerializer < ActiveModel::Serializer
3
+ attributes :id, :transaction_type, :amount, :transaction_reference, :status,
4
+ :created_at, :updated_at
5
+
6
+ belongs_to :loan, serializer: LoanSerializer
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module Dscf::Credit
2
+ class PaymentRequestSerializer < ActiveModel::Serializer
3
+ attributes :id, :order_id, :request_type, :amount, :receiver_account_reference,
4
+ :status, :failure_reason, :initiated_at, :approved_at, :created_at, :updated_at
5
+
6
+ belongs_to :user, serializer: Dscf::Core::UserSerializer
7
+ has_many :loans, serializer: Dscf::Credit::LoanSerializer
8
+ has_many :payments, serializer: Dscf::Credit::PaymentSerializer
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Dscf::Credit
2
+ class PaymentSerializer < ActiveModel::Serializer
3
+ attributes :id, :amount, :receiver_account_reference, :transaction_reference,
4
+ :status, :failure_reason, :processed_at, :created_at, :updated_at
5
+
6
+ belongs_to :payment_request, serializer: PaymentRequestSerializer
7
+ end
8
+ end
@@ -9,5 +9,7 @@ module Dscf::Credit
9
9
  belongs_to :scoring_param_type, serializer: Dscf::Credit::ScoringParamTypeSerializer
10
10
  belongs_to :previous_version, serializer: Dscf::Credit::ScoringParameterSerializer
11
11
  has_many :parameter_normalizers, serializer: Dscf::Credit::ParameterNormalizerSerializer
12
+ has_many :scoring_tables, serializer: Dscf::Credit::ScoringTableSerializer
13
+ has_many :categories, serializer: Dscf::Credit::CategorySerializer
12
14
  end
13
15
  end
@@ -2,7 +2,7 @@ module Dscf::Credit
2
2
  class ScoringTableSerializer < ActiveModel::Serializer
3
3
  attributes :id, :weight, :active, :created_at, :updated_at
4
4
 
5
- belongs_to :credit_line, serializer: Dscf::Credit::CreditLineSerializer
5
+ belongs_to :category, serializer: Dscf::Credit::CategorySerializer
6
6
  belongs_to :scoring_parameter, serializer: Dscf::Credit::ScoringParameterSerializer
7
7
  belongs_to :created_by, serializer: Dscf::Core::UserSerializer
8
8
  end
@@ -0,0 +1,153 @@
1
+ module Dscf::Credit
2
+ class CreditLimitCalculationService
3
+ attr_reader :loan_profile, :category
4
+
5
+ def initialize(loan_profile, category)
6
+ @loan_profile = loan_profile
7
+ @category = category
8
+ end
9
+
10
+ # Calculate credit limits for all credit lines in a category for a specific loan profile
11
+ # @return [Hash] Result containing eligible credit lines with calculated limits
12
+ def calculate_credit_limits
13
+ return error_result("Loan profile not found") unless loan_profile
14
+ return error_result("Category not found") unless category
15
+
16
+ scoring_spec = loan_profile.loan_profile_scoring_specs.active.first
17
+ return error_result("No active scoring found for loan profile") unless scoring_spec
18
+
19
+ credit_lines = category.credit_lines.approved.includes(:bank, :category, :credit_line_specs)
20
+ return error_result("No approved credit lines found for category") if credit_lines.empty?
21
+
22
+ eligible_credit_lines = calculate_limits_for_credit_lines(credit_lines, scoring_spec)
23
+
24
+ success_result(eligible_credit_lines)
25
+ rescue StandardError => e
26
+ error_result("Credit limit calculation failed: #{e.message}")
27
+ end
28
+
29
+ private
30
+
31
+ def calculate_limits_for_credit_lines(credit_lines, scoring_spec)
32
+ results = []
33
+
34
+ credit_lines.each do |credit_line|
35
+ limit_data = calculate_individual_credit_limit(credit_line, scoring_spec)
36
+ next if limit_data[:credit_limit] <= 0
37
+
38
+ eligible_credit_line = find_or_create_eligible_credit_line(credit_line)
39
+ eligible_credit_line.assign_attributes(limit_data)
40
+
41
+ if eligible_credit_line.save
42
+ results << {
43
+ credit_line: credit_line,
44
+ eligible_credit_line: eligible_credit_line,
45
+ calculated_limit: limit_data[:credit_limit],
46
+ available_limit: limit_data[:available_limit],
47
+ risk_factor: limit_data[:risk]
48
+ }
49
+ end
50
+ end
51
+
52
+ results
53
+ end
54
+
55
+ def calculate_individual_credit_limit(credit_line, scoring_spec)
56
+ base_limit = scoring_spec.total_limit
57
+
58
+ credit_line_specs = credit_line.credit_line_specs.active
59
+ adjusted_limit = apply_credit_line_specifications(base_limit, credit_line_specs)
60
+
61
+ risk_factor = calculate_risk_factor(credit_line, loan_profile)
62
+ final_limit = adjusted_limit * (1 - risk_factor)
63
+
64
+ used_limit = calculate_used_limit(credit_line)
65
+ available_limit = [ final_limit - used_limit, 0 ].max
66
+
67
+ {
68
+ credit_limit: final_limit.round(2),
69
+ available_limit: available_limit.round(2),
70
+ risk: risk_factor.round(4)
71
+ }
72
+ end
73
+
74
+ def apply_credit_line_specifications(base_limit, credit_line_specs)
75
+ return base_limit if credit_line_specs.empty?
76
+
77
+ spec = credit_line_specs.first
78
+ return base_limit unless spec
79
+
80
+ if spec.credit_line_multiplier && spec.credit_line_multiplier > 0
81
+ adjustment_factor = spec.credit_line_multiplier / 30.0 # Normalize against default 30 days
82
+ adjusted_limit = base_limit * adjustment_factor
83
+ else
84
+ adjusted_limit = base_limit
85
+ end
86
+
87
+ if spec.max_amount && adjusted_limit > spec.max_amount
88
+ adjusted_limit = spec.max_amount
89
+ end
90
+
91
+ if spec.min_amount && adjusted_limit < spec.min_amount
92
+ adjusted_limit = spec.min_amount
93
+ end
94
+
95
+ adjusted_limit
96
+ end
97
+
98
+ def calculate_risk_factor(credit_line, loan_profile)
99
+ base_risk = 0.1 # 10% base risk
100
+
101
+ # Increase risk based on loan profile characteristics
102
+ risk_adjustments = 0.0
103
+
104
+ # Risk based on previous loan performance
105
+ if loan_profile.loans.overdue.any?
106
+ risk_adjustments += 0.2 # 20% additional risk for overdue loans
107
+ end
108
+
109
+ # Risk based on available amount vs total amount ratio
110
+ if loan_profile.total_amount > 0
111
+ utilization_ratio = (loan_profile.total_amount - loan_profile.available_amount) / loan_profile.total_amount
112
+ risk_adjustments += utilization_ratio * 0.1 # Up to 10% additional risk
113
+ end
114
+
115
+ # Risk based on credit line category
116
+ case credit_line.category.name.downcase
117
+ when "high_risk"
118
+ risk_adjustments += 0.15
119
+ when "medium_risk"
120
+ risk_adjustments += 0.05
121
+ end
122
+
123
+ # Cap total risk at 90%
124
+ [ base_risk + risk_adjustments, 0.9 ].min
125
+ end
126
+
127
+ def calculate_used_limit(credit_line)
128
+ credit_line.loans.where(status: [ "active", "overdue" ]).sum(:remaining_amount)
129
+ end
130
+
131
+ def find_or_create_eligible_credit_line(credit_line)
132
+ loan_profile.eligible_credit_lines.find_or_initialize_by(credit_line: credit_line)
133
+ end
134
+
135
+ def success_result(eligible_credit_lines)
136
+ {
137
+ success: true,
138
+ data: eligible_credit_lines,
139
+ message: "Credit limits calculated successfully",
140
+ count: eligible_credit_lines.size
141
+ }
142
+ end
143
+
144
+ def error_result(message)
145
+ {
146
+ success: false,
147
+ data: [],
148
+ error: message,
149
+ count: 0
150
+ }
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,180 @@
1
+ module Dscf::Credit
2
+ class DisbursementService
3
+ attr_reader :credit_line, :payment_request, :current_user
4
+
5
+ def initialize(credit_line, payment_request, current_user)
6
+ @credit_line = credit_line
7
+ @payment_request = payment_request
8
+ @current_user = current_user
9
+ end
10
+
11
+ # Process disbursement by creating a loan record from selected credit line
12
+ # @return [Hash] Result containing created loan and disbursement details
13
+ def process_disbursement
14
+ return error_result("Credit line not found") unless credit_line
15
+ return error_result("Payment request not found") unless payment_request
16
+ return error_result("Credit line is not approved") unless credit_line.status == "approved"
17
+
18
+ eligible_credit_line = find_eligible_credit_line
19
+ return error_result("No eligible credit line found") unless eligible_credit_line
20
+
21
+ loan_profile = eligible_credit_line.loan_profile
22
+ return error_result("Loan profile not approved") unless loan_profile.status == "approved"
23
+
24
+ validation_result = validate_disbursement_amount(eligible_credit_line)
25
+ return validation_result unless validation_result[:success]
26
+
27
+ ActiveRecord::Base.transaction do
28
+ loan = create_loan_record(loan_profile, eligible_credit_line)
29
+ process_payment_and_charges(loan)
30
+ update_credit_line_limits(eligible_credit_line, loan)
31
+ lock_other_credit_lines(loan_profile, credit_line)
32
+
33
+ success_result(loan)
34
+ end
35
+ rescue StandardError => e
36
+ error_result("Disbursement processing failed: #{e.message}")
37
+ end
38
+
39
+ private
40
+
41
+ def find_eligible_credit_line
42
+ credit_line.eligible_credit_lines
43
+ .joins(:loan_profile)
44
+ .where(dscf_credit_loan_profiles: { status: "approved" })
45
+ .first
46
+ end
47
+
48
+ def validate_disbursement_amount(eligible_credit_line)
49
+ requested_amount = payment_request.amount
50
+ available_limit = eligible_credit_line.available_limit
51
+
52
+ if requested_amount <= 0
53
+ return error_result("Invalid disbursement amount")
54
+ end
55
+
56
+ if requested_amount > available_limit
57
+ return error_result("Requested amount exceeds available credit limit")
58
+ end
59
+
60
+ { success: true }
61
+ end
62
+
63
+ def create_loan_record(loan_profile, eligible_credit_line)
64
+ loan_terms = calculate_loan_terms(eligible_credit_line)
65
+
66
+ loan = Dscf::Credit::Loan.new(
67
+ loan_profile: loan_profile,
68
+ credit_line: credit_line,
69
+ payment_request: payment_request,
70
+ principal_amount: payment_request.amount,
71
+ facilitation_fee: loan_terms[:facilitation_fee],
72
+ total_loan_amount: loan_terms[:total_amount],
73
+ remaining_amount: loan_terms[:total_amount],
74
+ accrued_interest: 0,
75
+ accrued_penalty: 0,
76
+ status: "disbursed",
77
+ due_date: loan_terms[:due_date],
78
+ disbursed_at: Time.current
79
+ )
80
+
81
+ raise "Failed to create loan: #{loan.errors.full_messages.join(', ')}" unless loan.save
82
+
83
+ loan
84
+ end
85
+
86
+ def calculate_loan_terms(eligible_credit_line)
87
+ principal = payment_request.amount
88
+
89
+ credit_line_spec = credit_line.credit_line_specs.active.first
90
+
91
+ if credit_line_spec
92
+ facilitation_rate = credit_line_spec.facilitation_fee_rate
93
+ vat_rate = credit_line_spec.vat
94
+ loan_duration = credit_line_spec.loan_duration
95
+ else
96
+ facilitation_rate = 0.02 # 2%
97
+ vat_rate = 0.15 # 15%
98
+ loan_duration = 30 # 30 days
99
+ end
100
+
101
+ facilitation_fee = principal * facilitation_rate
102
+ vat_amount = facilitation_fee * vat_rate
103
+ total_amount = principal + facilitation_fee + vat_amount
104
+
105
+ due_date = Date.current + loan_duration.days
106
+
107
+ {
108
+ facilitation_fee: facilitation_fee.round(2),
109
+ vat_amount: vat_amount.round(2),
110
+ total_amount: total_amount.round(2),
111
+ due_date: due_date
112
+ }
113
+ end
114
+
115
+ def process_payment_and_charges(loan)
116
+ payment_request.update!(
117
+ status: "processed",
118
+ approved_at: Time.current
119
+ )
120
+
121
+ Dscf::Credit::LoanTransaction.create!(
122
+ loan: loan,
123
+ transaction_type: "disbursement",
124
+ amount: loan.principal_amount,
125
+ transaction_reference: "DISB-#{payment_request.order_id}-#{Time.current.to_i}",
126
+ status: "completed"
127
+ )
128
+
129
+ if loan.facilitation_fee > 0
130
+ Dscf::Credit::LoanTransaction.create!(
131
+ loan: loan,
132
+ transaction_type: "fee_charge",
133
+ amount: loan.facilitation_fee,
134
+ transaction_reference: "FEE-#{loan.id}-#{Time.current.to_i}",
135
+ status: "completed"
136
+ )
137
+ end
138
+ end
139
+
140
+ def update_credit_line_limits(eligible_credit_line, loan)
141
+ new_available_limit = eligible_credit_line.available_limit - loan.total_loan_amount
142
+ eligible_credit_line.update!(available_limit: [ new_available_limit, 0 ].max)
143
+
144
+ # Update loan profile available amount
145
+ loan_profile = eligible_credit_line.loan_profile
146
+ new_profile_available = loan_profile.available_amount - loan.total_loan_amount
147
+ loan_profile.update!(available_amount: [ new_profile_available, 0 ].max)
148
+ end
149
+
150
+ def lock_other_credit_lines(loan_profile, current_credit_line)
151
+ other_eligible_lines = loan_profile.eligible_credit_lines
152
+ .where.not(credit_line: current_credit_line)
153
+
154
+ other_eligible_lines.update_all(available_limit: 0)
155
+ end
156
+
157
+ def success_result(loan)
158
+ {
159
+ success: true,
160
+ loan: loan,
161
+ disbursement_details: {
162
+ principal_amount: loan.principal_amount,
163
+ facilitation_fee: loan.facilitation_fee,
164
+ total_loan_amount: loan.total_loan_amount,
165
+ due_date: loan.due_date,
166
+ disbursed_at: loan.disbursed_at
167
+ },
168
+ message: "Disbursement processed successfully"
169
+ }
170
+ end
171
+
172
+ def error_result(message)
173
+ {
174
+ success: false,
175
+ loan: nil,
176
+ error: message
177
+ }
178
+ end
179
+ end
180
+ end
@@ -7,12 +7,11 @@ module Dscf::Credit
7
7
  @approver = approver
8
8
  end
9
9
 
10
- def approve(total_limit = nil)
10
+ def approve
11
11
  ActiveRecord::Base.transaction do
12
12
  facilitator.update!(
13
13
  kyc_status: "approved",
14
- kyc_approved_by: approver,
15
- total_limit: total_limit
14
+ kyc_reviewed_by: approver
16
15
  )
17
16
 
18
17
  token = generate_additional_info_token
@@ -33,7 +32,7 @@ module Dscf::Credit
33
32
  ActiveRecord::Base.transaction do
34
33
  facilitator.update!(
35
34
  kyc_status: "rejected",
36
- kyc_approved_by: approver,
35
+ kyc_reviewed_by: approver,
37
36
  review_feedback: review_feedback
38
37
  )
39
38