dscf-credit 0.1.4 → 0.1.5

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/dscf/core/copilot-instructions.md +683 -0
  3. data/app/controllers/concerns/dscf/core/reviewable_controller.rb +347 -0
  4. data/app/controllers/dscf/credit/categories_controller.rb +3 -3
  5. data/app/controllers/dscf/credit/credit_lines_controller.rb +21 -13
  6. data/app/controllers/dscf/credit/eligible_credit_lines_controller.rb +50 -8
  7. data/app/controllers/dscf/credit/facilitator_applications_controller.rb +35 -0
  8. data/app/controllers/dscf/credit/facilitators_controller.rb +8 -96
  9. data/app/controllers/dscf/credit/loan_applications_controller.rb +252 -0
  10. data/app/controllers/dscf/credit/loan_profiles_controller.rb +61 -68
  11. data/app/controllers/dscf/credit/payment_requests_controller.rb +3 -5
  12. data/app/controllers/dscf/credit/scoring_parameters_controller.rb +59 -13
  13. data/app/controllers/dscf/credit/system_configs_controller.rb +30 -12
  14. data/app/models/concerns/core/reviewable_model.rb +31 -0
  15. data/app/models/dscf/credit/bank.rb +3 -3
  16. data/app/models/dscf/credit/bank_branch.rb +1 -1
  17. data/app/models/dscf/credit/category.rb +1 -2
  18. data/app/models/dscf/credit/credit_line.rb +4 -10
  19. data/app/models/dscf/credit/eligible_credit_line.rb +2 -2
  20. data/app/models/dscf/credit/facilitator.rb +6 -17
  21. data/app/models/dscf/credit/facilitator_application.rb +20 -0
  22. data/app/models/dscf/credit/loan_application.rb +30 -0
  23. data/app/models/dscf/credit/loan_profile.rb +10 -30
  24. data/app/models/dscf/credit/parameter_normalizer.rb +1 -1
  25. data/app/models/dscf/credit/scoring_parameter.rb +5 -7
  26. data/app/models/dscf/credit/system_config.rb +4 -9
  27. data/app/serializers/dscf/credit/category_serializer.rb +0 -1
  28. data/app/serializers/dscf/credit/credit_line_serializer.rb +2 -2
  29. data/app/serializers/dscf/credit/facilitator_application_serializer.rb +7 -0
  30. data/app/serializers/dscf/credit/facilitator_serializer.rb +3 -6
  31. data/app/serializers/dscf/credit/loan_application_serializer.rb +12 -0
  32. data/app/serializers/dscf/credit/loan_profile_serializer.rb +3 -6
  33. data/app/serializers/dscf/credit/scoring_parameter_serializer.rb +3 -4
  34. data/app/serializers/dscf/credit/system_config_serializer.rb +2 -2
  35. data/app/services/dscf/credit/credit_scoring_engine.rb +258 -0
  36. data/app/services/dscf/credit/facility_limit_calculation_engine.rb +159 -0
  37. data/app/services/dscf/credit/loan_profile_creation_service.rb +91 -0
  38. data/app/services/dscf/credit/risk_application_service.rb +61 -11
  39. data/config/locales/en.yml +63 -48
  40. data/config/routes.rb +31 -17
  41. data/db/migrate/20250822091131_create_dscf_credit_credit_lines.rb +1 -8
  42. data/db/migrate/20250822091820_create_dscf_credit_system_configs.rb +0 -7
  43. data/db/migrate/20250822092050_create_dscf_credit_scoring_parameters.rb +2 -6
  44. data/db/migrate/20250822092225_create_dscf_credit_parameter_normalizers.rb +1 -1
  45. data/db/migrate/20250822092236_create_dscf_credit_loan_applications.rb +20 -0
  46. data/db/migrate/20250822092246_create_dscf_credit_loan_profiles.rb +7 -19
  47. data/db/migrate/20250822092426_create_dscf_credit_facilitator_applications.rb +10 -0
  48. data/db/migrate/20250822092436_create_dscf_credit_facilitators.rb +1 -16
  49. data/db/seeds.rb +316 -203
  50. data/lib/dscf/credit/version.rb +1 -1
  51. data/spec/factories/dscf/credit/banks.rb +1 -1
  52. data/spec/factories/dscf/credit/credit_lines.rb +0 -23
  53. data/spec/factories/dscf/credit/facilitator_applications.rb +37 -0
  54. data/spec/factories/dscf/credit/facilitators.rb +8 -30
  55. data/spec/factories/dscf/credit/loan_applications.rb +42 -0
  56. data/spec/factories/dscf/credit/loan_profiles.rb +20 -34
  57. data/spec/factories/dscf/credit/parameter_normalizers.rb +4 -4
  58. data/spec/factories/dscf/credit/scoring_parameters.rb +14 -11
  59. data/spec/factories/dscf/credit/system_configs.rb +21 -5
  60. metadata +20 -10
  61. data/app/controllers/concerns/dscf/credit/reviewable.rb +0 -112
  62. data/app/controllers/dscf/credit/scoring_tables_controller.rb +0 -63
  63. data/app/models/dscf/credit/scoring_table.rb +0 -24
  64. data/app/serializers/dscf/credit/scoring_table_serializer.rb +0 -9
  65. data/db/migrate/20250901172842_create_dscf_credit_scoring_tables.rb +0 -18
  66. data/spec/factories/dscf/credit/scoring_tables.rb +0 -25
@@ -0,0 +1,347 @@
1
+ module Dscf
2
+ module Core
3
+ module ReviewableController
4
+ extend ActiveSupport::Concern
5
+ include Dscf::Core::JsonResponse
6
+
7
+ included do
8
+ class_attribute :review_context_configs, default: {}
9
+ class_attribute :reviewable_model_class, default: nil
10
+
11
+ # Initialize with default context config for zero-config support
12
+ self.review_context_configs = default_context_config.dup
13
+
14
+ # Auto-define default actions for zero-config
15
+ define_default_review_actions
16
+
17
+ before_action :set_reviewable_resource, if: :review_action?
18
+ before_action :authorize_review_action!, if: :review_action?
19
+ end
20
+
21
+ class_methods do
22
+ def reviewable_model(model_class)
23
+ self.reviewable_model_class = model_class
24
+ end
25
+
26
+ def reviewable_context(context_name, options = {})
27
+ statuses = options[:statuses]&.map(&:to_s) || %w[pending approved rejected modify]
28
+ initial_status = options[:initial_status]&.to_s || "pending"
29
+
30
+ # Convert linear transitions array to hash if provided
31
+ transitions = if options[:transitions].is_a?(Array)
32
+ validate_linear_transitions(options[:transitions], statuses, context_name)
33
+ build_linear_transitions(options[:transitions])
34
+ else
35
+ options[:transitions] || {}
36
+ end
37
+
38
+ defaults = {
39
+ statuses: statuses,
40
+ initial_status: initial_status,
41
+ transitions: transitions,
42
+ actions: options[:actions] || default_actions
43
+ }
44
+
45
+ validate_action_config(defaults[:actions], defaults[:statuses], context_name)
46
+ unless defaults[:statuses].include?(defaults[:initial_status])
47
+ raise ArgumentError,
48
+ "Initial status '#{defaults[:initial_status]}' in context '#{context_name}' must be one of: #{defaults[:statuses].join(', ')}"
49
+ end
50
+
51
+ # Add to existing configs instead of replacing them
52
+ self.review_context_configs = review_context_configs.merge(context_name.to_sym => defaults)
53
+
54
+ # Define methods for all actions in this context
55
+ defaults[:actions].each_key do |action_name|
56
+ # Only define if not already defined
57
+ define_review_action_method(action_name) unless method_defined?(action_name)
58
+ end
59
+ end
60
+
61
+ def define_default_review_actions
62
+ default_context_config.each do |context_name, config|
63
+ validate_action_config(config[:actions], config[:statuses], context_name)
64
+ config[:actions].each_key do |action_name|
65
+ define_review_action_method(action_name)
66
+ end
67
+ end
68
+ end
69
+
70
+ def define_review_action_method(action_name)
71
+ define_method(action_name) do
72
+ context = current_review_context
73
+ action_config = context_config[:actions][action_name.to_sym]
74
+ unless action_config
75
+ return render_error(
76
+ errors: [ "Action '#{action_name}' not defined for context '#{context}'" ],
77
+ status: :bad_request
78
+ )
79
+ end
80
+ perform_review_action(**action_config.slice(:status, :require_feedback, :after, :update_model))
81
+ end
82
+ end
83
+
84
+ def default_actions
85
+ {
86
+ approve: { status: "approved" },
87
+ reject: { status: "rejected", require_feedback: true },
88
+ request_modification: { status: "modify", require_feedback: true },
89
+ resubmit: { status: "pending", update_model: true }
90
+ }
91
+ end
92
+
93
+ def default_context_config
94
+ {
95
+ default: {
96
+ statuses: %w[pending approved rejected modify],
97
+ initial_status: "pending",
98
+ transitions: { "pending" => %w[approved rejected modify], "modify" => [ "pending" ] },
99
+ actions: default_actions
100
+ }
101
+ }
102
+ end
103
+
104
+ def validate_action_config(actions, statuses, context_name)
105
+ actions.each do |action_name, opts|
106
+ unless statuses.include?(opts[:status])
107
+ raise ArgumentError,
108
+ "Action '#{action_name}' in context '#{context_name}' maps to invalid status '#{opts[:status]}'. Must be one of: #{statuses.join(', ')}"
109
+ end
110
+ end
111
+ end
112
+
113
+ def validate_linear_transitions(transitions, statuses, context_name)
114
+ transitions.each do |status|
115
+ unless statuses.include?(status.to_s)
116
+ raise ArgumentError, "Transition status '#{status}' in context '#{context_name}' must be one of: #{statuses.join(', ')}"
117
+ end
118
+ end
119
+ end
120
+
121
+ def build_linear_transitions(transitions)
122
+ transitions.each_with_object({}).with_index do |(status, hash), index|
123
+ next_status = transitions[index + 1]
124
+ hash[status.to_s] = next_status ? [ next_status.to_s ] : []
125
+ end
126
+ end
127
+
128
+ def review_action_names
129
+ # Get actions from initialized contexts + default fallback
130
+ all_actions = review_context_configs.values.flat_map { |config| config[:actions].keys }
131
+ all_actions += default_context_config[:default][:actions].keys
132
+ all_actions.uniq
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def review_action?
139
+ self.class.review_action_names.include?(action_name.to_sym)
140
+ end
141
+
142
+ def perform_review_action(status:, require_feedback: false, after: nil, update_model: false)
143
+ # Validate context exists before proceeding
144
+ begin
145
+ context_config
146
+ rescue ArgumentError => e
147
+ return render_error(errors: [ e.message ], status: :bad_request)
148
+ end
149
+
150
+ current_review = reviewable_resource.current_review_for(current_review_context)
151
+
152
+ feedback = if require_feedback
153
+ feedback_data = params[:review_feedback].presence || params.dig(:review_feedback)&.to_unsafe_h
154
+ return render_error(errors: [ "Feedback is required for #{status}" ]) if feedback_data.blank?
155
+
156
+ feedback_data
157
+ else
158
+ nil
159
+ end
160
+
161
+ unless valid_transition?(current_review&.status, status)
162
+ return render_error(errors: [ "Cannot transition from '#{current_review&.status || context_config[:initial_status]}' to '#{status}'" ])
163
+ end
164
+
165
+ begin
166
+ ActiveRecord::Base.transaction do
167
+ # Update the model if required (e.g., for resubmit with changes)
168
+ if update_model
169
+ begin
170
+ model_updates = model_params
171
+ if model_updates.present? && !reviewable_resource.update(model_updates)
172
+ return render_error(errors: reviewable_resource.errors.full_messages)
173
+ end
174
+ rescue ActionController::ParameterMissing => e
175
+ return render_error(errors: [ e.message ])
176
+ end
177
+ end
178
+
179
+ # Update existing review or create new one if none exists
180
+ review = current_review || reviewable_resource.build_review_for(current_review_context)
181
+ review.assign_attributes(
182
+ status: status,
183
+ feedback: feedback,
184
+ reviewed_by: current_user,
185
+ reviewed_at: Time.current
186
+ )
187
+
188
+ before_review_action(review)
189
+ review.save!
190
+ execute_after_callbacks(review, after)
191
+ after_review_action(review)
192
+ end
193
+ render_success(data: reviewable_resource.reload)
194
+ rescue StandardError => e
195
+ render_error(errors: [ e.message ], status: :unprocessable_entity)
196
+ end
197
+ end
198
+
199
+ def execute_after_callbacks(review, after_callbacks = nil)
200
+ # Get action callbacks from the current action config or passed callbacks
201
+ action_config = context_config[:actions][action_name.to_sym]
202
+ action_callbacks = after_callbacks || action_config&.[](:after)
203
+ return unless action_callbacks
204
+
205
+ Array(action_callbacks).each do |callback|
206
+ if callback.is_a?(Symbol)
207
+ send(callback, review)
208
+ elsif callback.respond_to?(:call)
209
+ callback.call(review)
210
+ else
211
+ raise "Invalid callback: #{callback.inspect}"
212
+ end
213
+ rescue StandardError => e
214
+ Rails.logger.error "Callback failed: #{callback.inspect}, error: #{e.message}"
215
+ raise
216
+ end
217
+ end
218
+
219
+ def current_review_context
220
+ params[:context]&.to_sym || :default
221
+ end
222
+
223
+ def available_contexts
224
+ # Get all configured contexts plus default if not explicitly configured
225
+ contexts = self.class.review_context_configs.keys
226
+ contexts << :default unless contexts.include?(:default)
227
+ contexts
228
+ end
229
+
230
+ def context_config
231
+ context = current_review_context
232
+ config = self.class.review_context_configs[context]
233
+
234
+ # If requesting default context and it's not configured, use the built-in default
235
+ config = self.class.default_context_config[:default] if context == :default && config.nil?
236
+
237
+ # If context is not found and it's not the default, it's invalid
238
+ raise ArgumentError, "Invalid context '#{context}'. Available contexts: #{available_contexts.join(', ')}" if config.nil?
239
+
240
+ Rails.logger.debug "Context config for '#{context}': #{config.inspect}"
241
+ config
242
+ end
243
+
244
+ def allowed_statuses
245
+ context_config[:statuses]
246
+ end
247
+
248
+ def valid_transition?(from, to)
249
+ return true if context_config[:transitions].blank?
250
+
251
+ allowed_to = context_config[:transitions][from || context_config[:initial_status]] || []
252
+ allowed_to.include?(to)
253
+ end
254
+
255
+ def authorize_review_action!
256
+ # Override for custom auth
257
+ end
258
+
259
+ def before_review_action(review)
260
+ # Default implementation - can be overridden
261
+ # Check if there's a custom hook method defined
262
+ return unless respond_to?(:before_reviewable_action, true)
263
+
264
+ before_reviewable_action(review, reviewable_resource, current_review_context)
265
+
266
+ # Custom pre-save logic override point
267
+ end
268
+
269
+ def after_review_action(review)
270
+ # New hook for post-action logic
271
+ return unless respond_to?(:after_reviewable_action, true)
272
+
273
+ after_reviewable_action(review, reviewable_resource, current_review_context)
274
+ end
275
+
276
+ def current_user
277
+ # Default implementation that can be overridden
278
+ # Check if there's a custom user method defined
279
+ if respond_to?(:current_reviewer, true)
280
+ current_reviewer
281
+ else
282
+ # Default fallback - can be overridden in controllers
283
+ # Try common patterns or return nil if none exist
284
+ return super if defined?(super)
285
+ return @current_user if defined?(@current_user)
286
+ return session[:user_id] if session && session[:user_id]
287
+
288
+ nil
289
+ end
290
+ end
291
+
292
+ def model_params
293
+ # Default implementation that can be overridden
294
+ # Try different common parameter patterns
295
+ resource_name = controller_name.singularize
296
+
297
+ # First try the standard Rails pattern: resource_name_params
298
+ params_method = "#{resource_name}_params"
299
+ return send(params_method) if respond_to?(params_method, true)
300
+
301
+ # Fallback to generic reviewable_params
302
+ return reviewable_params if respond_to?(:reviewable_params, true)
303
+
304
+ # If neither exists, return empty hash (no model updates)
305
+ {}
306
+ rescue ActionController::ParameterMissing => e
307
+ raise e # Re-raise parameter missing errors
308
+ rescue StandardError => e
309
+ Rails.logger.warn "Failed to get model params: #{e.message}"
310
+ {}
311
+ end
312
+
313
+ def model_class
314
+ return reviewable_model_class if reviewable_model_class
315
+
316
+ model_name = controller_name.classify
317
+
318
+ controller_namespace = self.class.name.deconstantize
319
+ if controller_namespace.present?
320
+ namespaced_model = "#{controller_namespace}::#{model_name}"
321
+ return namespaced_model.constantize if Object.const_defined?(namespaced_model)
322
+ end
323
+
324
+ return model_name.constantize if Object.const_defined?(model_name)
325
+
326
+ raise NameError, "Could not determine model class for #{self.class.name}. " \
327
+ "Please configure it explicitly using 'reviewable_model ModelClass' " \
328
+ "in your controller class."
329
+ rescue NameError => e
330
+ Rails.logger.error "Model resolution failed for #{self.class.name}: #{e.message}"
331
+ raise
332
+ end
333
+
334
+ def set_reviewable_resource
335
+ @reviewable_resource = model_class.find(params[:id])
336
+ rescue ActiveRecord::RecordNotFound => e
337
+ render_error(status: :not_found, errors: [ e.message ])
338
+ rescue NameError => e
339
+ render_error(status: :internal_server_error, errors: [ "Configuration error: #{e.message}" ])
340
+ end
341
+
342
+ def reviewable_resource
343
+ @reviewable_resource
344
+ end
345
+ end
346
+ end
347
+ end
@@ -14,7 +14,7 @@ module Dscf::Credit
14
14
  end
15
15
 
16
16
  def eager_loaded_associations
17
- [ :credit_lines, :scoring_tables, :scoring_parameters ]
17
+ [ :credit_lines, :scoring_parameters ]
18
18
  end
19
19
 
20
20
  def allowed_order_columns
@@ -24,9 +24,9 @@ module Dscf::Credit
24
24
  def default_serializer_includes
25
25
  {
26
26
  index: [],
27
- show: [ :credit_lines, :scoring_tables, :scoring_parameters ],
27
+ show: [ :credit_lines, :scoring_parameters ],
28
28
  create: [],
29
- update: [ :credit_lines, :scoring_tables, :scoring_parameters ]
29
+ update: [ :credit_lines, :scoring_parameters ]
30
30
  }
31
31
  end
32
32
  end
@@ -1,12 +1,16 @@
1
1
  module Dscf::Credit
2
2
  class CreditLinesController < ApplicationController
3
3
  include Dscf::Core::Common
4
- include Dscf::Credit::Reviewable
4
+ include Dscf::Core::ReviewableController
5
5
 
6
6
  def create
7
7
  super do
8
8
  credit_line = @clazz.new(model_params)
9
9
  credit_line.created_by = current_user
10
+ credit_line.reviews.build(
11
+ status: "pending",
12
+ context: "default",
13
+ )
10
14
  credit_line
11
15
  end
12
16
  end
@@ -20,29 +24,33 @@ module Dscf::Credit
20
24
  :name,
21
25
  :code,
22
26
  :description,
23
- :status,
24
- :reviewed_by_type,
25
- :reviewed_by_id,
26
- :review_date,
27
- :document_reference,
28
- :review_feedback
27
+ :document_reference
29
28
  )
30
29
  end
31
30
 
32
31
  def eager_loaded_associations
33
- [ :bank, :category, :created_by, :reviewed_by, :credit_line_specs, :loans, :eligible_credit_lines ]
32
+ [
33
+ :bank, :category, :created_by, :credit_line_specs, :loans, :eligible_credit_lines,
34
+ reviews: { reviewed_by: :user_profile }
35
+ ]
34
36
  end
35
37
 
36
38
  def allowed_order_columns
37
- %w[id name code status review_date created_at updated_at category_id]
39
+ %w[id name code created_at updated_at category_id]
38
40
  end
39
41
 
40
42
  def default_serializer_includes
41
43
  {
42
- index: [ :bank, :category ],
43
- show: [ :bank, :category, :created_by, :reviewed_by, :credit_line_specs, :loans, :eligible_credit_lines ],
44
- create: [ :bank, :category, :created_by, :reviewed_by ],
45
- update: [ :bank, :category, :created_by, :reviewed_by, :credit_line_specs, :loans, :eligible_credit_lines ]
44
+ index: [ :bank, :category, reviews: { reviewed_by: :user_profile } ],
45
+ show: [
46
+ :bank, :category, :created_by, :credit_line_specs, :loans, :eligible_credit_lines,
47
+ reviews: { reviewed_by: :user_profile }
48
+ ],
49
+ create: [ :bank, :category, :created_by, :reviews ],
50
+ update: [
51
+ :bank, :category, :created_by, :credit_line_specs, :loans, :eligible_credit_lines,
52
+ reviews: { reviewed_by: :user_profile }
53
+ ]
46
54
  }
47
55
  end
48
56
  end
@@ -2,31 +2,73 @@ module Dscf::Credit
2
2
  class EligibleCreditLinesController < ApplicationController
3
3
  include Dscf::Core::Common
4
4
 
5
- before_action :set_object, only: [ :show, :apply_risk ]
6
-
7
5
  def apply_risk
8
- unless params[:risk].present?
9
- return render_error("eligible_credit_line.errors.apply_risk", errors: [ "Risk parameter is required" ])
6
+ eligible_credit_line = @clazz.find(params[:id])
7
+ risk_factor = risk_params[:risk_factor]
8
+
9
+ if risk_factor.nil? || risk_factor == "" || (risk_factor.is_a?(Hash) && risk_factor.empty?)
10
+ return render_error(
11
+ "eligible_credit_line.errors.apply_risk",
12
+ errors: [ "Risk factor is required" ],
13
+ status: :unprocessable_entity
14
+ )
10
15
  end
11
16
 
12
- service = RiskApplicationService.new(@obj, params[:risk])
17
+ risk_factor_float = risk_factor.to_f
18
+ service = RiskApplicationService.new(eligible_credit_line, risk_factor_float)
13
19
  result = service.apply_risk
14
20
 
15
21
  if result[:success]
16
- render_success(data: result[:data].reload)
22
+ render_success(
23
+ "eligible_credit_line.success.apply_risk",
24
+ data: result[:data],
25
+ serializer_options: { include: [ :loan_profile, :credit_line ] }
26
+ )
27
+ else
28
+ render_error(
29
+ "eligible_credit_line.errors.apply_risk",
30
+ errors: result[:errors],
31
+ status: :unprocessable_entity
32
+ )
33
+ end
34
+ rescue ActiveRecord::RecordNotFound
35
+ render_error(
36
+ "eligible_credit_line.errors.not_found",
37
+ errors: [ "Eligible credit line not found" ],
38
+ status: :not_found
39
+ )
40
+ rescue => e
41
+ Rails.logger.error("Risk application error: #{e.class} - #{e.message}")
42
+ Rails.logger.error(e.backtrace.join("\n"))
43
+
44
+ if Rails.env.development? || Rails.env.test?
45
+ render_error(
46
+ "eligible_credit_line.errors.apply_risk",
47
+ errors: [ e.message ],
48
+ status: :unprocessable_entity
49
+ )
17
50
  else
18
- render_error(errors: result[:errors])
51
+ render_error(
52
+ "eligible_credit_line.errors.apply_risk",
53
+ errors: [ "An error occurred while applying risk factor" ],
54
+ status: :unprocessable_entity
55
+ )
19
56
  end
20
57
  end
21
58
 
22
59
  private
23
60
 
61
+ def risk_params
62
+ params.permit(:risk_factor)
63
+ end
64
+
24
65
  def model_params
25
66
  params.require(:eligible_credit_line).permit(
26
67
  :loan_profile_id,
27
68
  :credit_line_id,
28
69
  :credit_limit,
29
- :available_limit
70
+ :available_limit,
71
+ :risk
30
72
  )
31
73
  end
32
74
 
@@ -0,0 +1,35 @@
1
+ module Dscf::Credit
2
+ class FacilitatorApplicationsController < ApplicationController
3
+ include Dscf::Core::Common
4
+ include Dscf::Core::ReviewableController
5
+
6
+ def create
7
+ super
8
+ facilitator_application = @clazz.new(model_params)
9
+ facilitator_application.user = current_user
10
+ facilitator_application.reviews.build(context: "default", status: "pending")
11
+
12
+ facilitator_application
13
+ end
14
+
15
+ private
16
+
17
+ def model_params
18
+ params.require(:facilitator_application).permit(:user_id, :bank_id, facilitator_info: {})
19
+ end
20
+
21
+ def eager_loaded_associations
22
+ [ :user, :bank, reviews: { reviewed_by: :user_profile } ]
23
+ end
24
+
25
+ def allowed_order_columns
26
+ %w[id created_at updated_at]
27
+ end
28
+
29
+ def default_serializer_includes
30
+ {
31
+ default: [ :user, :bank, reviews: { reviewed_by: :user_profile } ]
32
+ }
33
+ end
34
+ end
35
+ end
@@ -1,116 +1,28 @@
1
1
  module Dscf::Credit
2
2
  class FacilitatorsController < ApplicationController
3
3
  include Dscf::Core::Common
4
-
5
- before_action :set_facilitator_for_approval, only: [ :approve, :reject, :set_limit ]
6
-
7
- def create
8
- super do
9
- begin
10
- FacilitatorCreationService.new(current_user, @clazz).create_single(model_params)
11
- rescue StandardError => e
12
- return render_error(errors: e.message)
13
- end
14
- end
15
- end
16
-
17
- def approve
18
- begin
19
- FacilitatorApprovalService.new(@facilitator, current_user).approve
20
- render_success(data: @facilitator)
21
- rescue StandardError => e
22
- render_error(errors: e.message)
23
- end
24
- end
25
-
26
- def reject
27
- begin
28
- FacilitatorApprovalService.new(@facilitator, current_user).reject(params[:review_feedback])
29
- render_success(data: @facilitator)
30
- rescue StandardError => e
31
- render_error(errors: e.message)
32
- end
33
- end
34
-
35
- def set_limit
36
- begin
37
- FacilitatorApprovalService.new(@facilitator, current_user).set_limit(params[:total_limit])
38
- render_success(data: @facilitator)
39
- rescue StandardError => e
40
- render_error(errors: e.message)
41
- end
42
- end
43
-
44
- def submit_additional_info
45
- facilitator_id = params[:id] || params[:facilitator_id]
46
- additional_info = params[:additional_info]&.permit!.to_h
47
-
48
- begin
49
- result = FacilitatorAdditionalInfoService.new.submit_info(facilitator_id, additional_info)
50
- render_success(data: result)
51
- rescue StandardError => e
52
- render_error(errors: e.message)
53
- end
54
- end
55
-
56
- def batch_create
57
- facilitators_params = params[:facilitators]
58
-
59
- begin
60
- service = FacilitatorCreationService.new(current_user, @clazz)
61
- results = service.create_batch(facilitators_params)
62
-
63
- if results[:failure_count] == 0
64
- render_success("facilitator.success.batch_created_all", data: results)
65
- elsif results[:success_count] == 0
66
- render_error("facilitator.errors.batch_failed_all", errors: results)
67
- else
68
- render json: {
69
- success: true,
70
- message: I18n.t("facilitator.success.batch_created_partial"),
71
- data: results
72
- }, status: :multi_status
73
- end
74
- rescue StandardError => e
75
- render_error("facilitator.errors.batch_creation_failed", errors: e.message)
76
- end
77
- end
4
+ include Dscf::Core::ReviewableController
78
5
 
79
6
  private
80
7
 
81
8
  def model_params
82
- params.require(:facilitator).permit(
83
- :user_id,
84
- :bank_id,
85
- :kyc_status,
86
- :total_limit,
87
- :kyc_review_date,
88
- :additional_info,
89
- :review_feedback
90
- )
91
- end
92
-
93
- def set_facilitator_for_approval
94
- @facilitator = @clazz.find(params[:id])
9
+ params.require(:facilitator).permit(:facilitator_application_id, :total_limit)
95
10
  end
96
11
 
97
12
  def eager_loaded_associations
98
- [ :user, :bank, :kyc_reviewed_by, :facilitator_performances ]
13
+ [ :facilitator_application, reviews: { reviewed_by: :user_profile } ]
99
14
  end
100
15
 
101
16
  def allowed_order_columns
102
- %w[id name type kyc_status total_limit kyc_review_date created_at updated_at]
17
+ %w[id total_limit created_at updated_at]
103
18
  end
104
19
 
105
20
  def default_serializer_includes
106
21
  {
107
- index: [ :user, :bank ],
108
- show: [ :user, :bank, :kyc_reviewed_by, :facilitator_performances ],
109
- create: [ :user, :bank, :kyc_reviewed_by ],
110
- update: [ :user, :bank, :kyc_reviewed_by, :facilitator_performances ],
111
- approve: [ :user, :bank, :kyc_reviewed_by, :facilitator_performances ],
112
- reject: [ :user, :bank, :kyc_reviewed_by ],
113
- set_limit: [ :user, :bank, :kyc_reviewed_by ]
22
+ index: [ :facilitator_application, reviews: { reviewed_by: :user_profile } ],
23
+ show: [ :facilitator_application, reviews: { reviewed_by: :user_profile } ],
24
+ create: [ :reviews ],
25
+ update: [ :facilitator_application, reviews: { reviewed_by: :user_profile } ]
114
26
  }
115
27
  end
116
28
  end