dscf-banking 0.3.5 → 0.3.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 033d842004e5e6c779e391bb9dca2e43925b3858212b50a94db2f3d8853a0dc1
4
- data.tar.gz: eb48ab4b6287afbf75f93801f033c08327d284f127142e7199a7678ee74b3acc
3
+ metadata.gz: f5ee5ccda8af113288e3eea6f69ba2a24b71d980850d72b25efb187b4f82579b
4
+ data.tar.gz: ab2d16dcde12321a0a18da6824e5f5788c10ca8aba568eb138085440187c3976
5
5
  SHA512:
6
- metadata.gz: f7bcc179bc00d1f81d16394e521b1d54188bd41efc89a0c0d1f9c076648eebc223a9642d3c21790bcb1270d649741b2692f54b74f7b6ec33cded00c44802d122
7
- data.tar.gz: b915c7adccc0fcde6e40717023d0f9fe849c5e81298d1797371a4876d5c9dce9dec294b1b08065d23873dd3c210d61b54922d33024ea23fbaf6f3adefe5dad04
6
+ metadata.gz: e68fcc9ad5dee13a9589181cede9394c2854c32d14db75e76618d523a2c8ec82a412acb867a62281477197e143a845b3d68299fe254d446e0158a059fe8f9bde
7
+ data.tar.gz: 99cdc4974f9c5068416f14c3fba844c3e7b023a1da84b0e42838f9aa88d0c4bc283824225344297f5afac92f4d7dd031d20390384d3538abcb9b5e8d6ad46c31
@@ -34,7 +34,7 @@ module Dscf::Banking
34
34
  user = account.application.user
35
35
  profile = user.respond_to?(:user_profile) ? user.user_profile : nil
36
36
  if profile
37
- full_name = [profile.first_name, profile.middle_name, profile.last_name].compact.join(" ")
37
+ full_name = [ profile.first_name, profile.middle_name, profile.last_name ].compact.join(" ")
38
38
  render json: { success: true, data: { full_name: full_name } }
39
39
  else
40
40
  render json: { success: false, error: "User profile not found" }, status: :not_found
@@ -231,29 +231,29 @@ module Dscf::Banking
231
231
 
232
232
  def transactions
233
233
  account = Dscf::Banking::Account.find(params[:id])
234
-
234
+
235
235
  transactions = Dscf::Banking::Transaction
236
236
  .where("account_id = ? OR debit_account_id = ? OR credit_account_id = ?", account.id, account.id, account.id)
237
237
  .includes(:account, :transaction_type, :debit_account, :credit_account)
238
-
238
+
239
239
  # Apply pagination if requested
240
240
  page = params[:page].to_i
241
241
  per_page = (params[:per_page] || 10).to_i
242
-
242
+
243
243
  # Apply filters
244
244
  transactions = transactions.where(status: params[:status]) if params[:status].present?
245
245
  transactions = transactions.where(transaction_type_id: params[:transaction_type_id]) if params[:transaction_type_id].present?
246
-
246
+
247
247
  # Apply ordering
248
248
  order_column = %w[id reference_number amount currency status created_at updated_at].include?(params[:order_by]) ? params[:order_by] : "created_at"
249
249
  order_direction = %w[asc desc].include?(params[:order_direction]) ? params[:order_direction] : "desc"
250
250
  transactions = transactions.order("#{order_column} #{order_direction}")
251
-
251
+
252
252
  if page.positive?
253
253
  total_count = transactions.count
254
254
  total_pages = (total_count.to_f / per_page).ceil
255
255
  transactions = transactions.offset((page - 1) * per_page).limit(per_page)
256
-
256
+
257
257
  render json: {
258
258
  success: true,
259
259
  message: "Account transactions retrieved successfully",
@@ -24,7 +24,7 @@ module Dscf::Banking
24
24
 
25
25
  private
26
26
 
27
- def application_data(application)
27
+ def application_data(application)
28
28
  {
29
29
  id: application.id,
30
30
  application_number: application.application_number,
@@ -52,7 +52,7 @@ module Dscf::Banking
52
52
  end
53
53
 
54
54
  def eager_loaded_associations
55
- [ :user, :virtual_account_product, :account, :documents, reviews: { reviewed_by: :user_profile } ]
55
+ [ :user, :virtual_account_product, :documents, reviews: { reviewed_by: :user_profile } ]
56
56
  end
57
57
 
58
58
  def allowed_order_columns
@@ -8,7 +8,7 @@ module Dscf::Banking
8
8
  super do
9
9
  documents = @application.documents
10
10
  options = { each_serializer: DocumentSerializer }
11
- [documents, options]
11
+ [ documents, options ]
12
12
  end
13
13
  end
14
14
 
@@ -16,17 +16,17 @@ module Dscf::Banking
16
16
  super do
17
17
  document = @application.documents.find(params[:id])
18
18
  options = { serializer: DocumentSerializer }
19
- [document, options]
19
+ [ document, options ]
20
20
  end
21
21
  end
22
22
 
23
23
  def create
24
24
  document = @application.documents.build(model_params)
25
-
25
+
26
26
  if document.save
27
27
  # Attach file if provided
28
28
  document.files.attach(params[:document][:file]) if params[:document][:file].present?
29
-
29
+
30
30
  render json: {
31
31
  success: true,
32
32
  data: DocumentSerializer.new(document).as_json
@@ -24,7 +24,7 @@ module Dscf::Banking
24
24
  end
25
25
 
26
26
  def eager_loaded_associations
27
- [ :virtual_account_product, :interest_rate_type ]
27
+ [ :virtual_account_product, :interest_rate_type, :interest_rate_tiers ]
28
28
  end
29
29
 
30
30
  def allowed_order_columns
@@ -33,8 +33,10 @@ module Dscf::Banking
33
33
 
34
34
  def default_serializer_includes
35
35
  {
36
- virtual_account_product: {},
37
- interest_rate_type: {}
36
+ index: [ :virtual_account_product, :interest_rate_type, :interest_rate_tiers ],
37
+ show: [ :virtual_account_product, :interest_rate_type, :interest_rate_tiers ],
38
+ create: [ :virtual_account_product, :interest_rate_type, :interest_rate_tiers ],
39
+ update: [ :virtual_account_product, :interest_rate_type, :interest_rate_tiers ]
38
40
  }
39
41
  end
40
42
  end
@@ -2,19 +2,25 @@ module Dscf::Banking
2
2
  class InterestConfiguration < ApplicationRecord
3
3
  belongs_to :interest_rate_type, class_name: "Dscf::Banking::InterestRateType"
4
4
  belongs_to :virtual_account_product, class_name: "Dscf::Banking::VirtualAccountProduct"
5
- has_many :interest_rate_tiers, class_name: "Dscf::Banking::InterestRateTier", dependent: :destroy
5
+ has_many :interest_rate_tiers, class_name: "Dscf::Banking::InterestRateTier", foreign_key: :interest_config_id, dependent: :destroy
6
6
 
7
- validates :annual_interest_rate, presence: true, numericality: { greater_than: 0, less_than_or_equal_to: 1 }
7
+ validates :annual_interest_rate, presence: true, numericality: { greater_than: 0, less_than_or_equal_to: 1 }, unless: :interest_free?
8
+ validates :annual_interest_rate, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1 }, if: :interest_free?, allow_nil: true
8
9
  validates :income_tax_rate, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1 }
9
10
  validates :minimum_balance_for_interest, presence: true, numericality: { greater_than_or_equal_to: 0 }
10
- validates :calculation_method, presence: true
11
-
12
- validates :interest_basis, presence: true
13
- validates :accrual_frequency, presence: true
14
- validates :rounding_rule, presence: true
15
- validates :calculation_timing, presence: true
11
+ validates :calculation_method, presence: true, unless: :interest_free?
12
+ validates :interest_basis, presence: true, unless: :interest_free?
13
+ validates :accrual_frequency, presence: true, unless: :interest_free?
14
+ validates :rounding_rule, presence: true, unless: :interest_free?
15
+ validates :calculation_timing, presence: true, unless: :interest_free?
16
16
  validates :is_active, inclusion: { in: [ true, false ] }
17
+
17
18
  validate :promotional_dates_consistency
19
+ validate :rate_type_specific_validations
20
+ validate :tiers_only_for_variable_rate
21
+ validate :interest_rate_type_requirements
22
+
23
+ before_validation :set_interest_basis_from_accrual_frequency
18
24
 
19
25
  enum :calculation_method, {
20
26
  simple: 0,
@@ -57,6 +63,33 @@ module Dscf::Banking
57
63
  scope :promotional, -> { where.not(promotional_start_date: nil, promotional_end_date: nil) }
58
64
  scope :current_promotional, -> { where("promotional_start_date <= ? AND promotional_end_date >= ?", Date.current, Date.current) }
59
65
 
66
+ def self.ransackable_attributes(auth_object = nil)
67
+ %w[id virtual_account_product_id interest_rate_type_id annual_interest_rate income_tax_rate
68
+ minimum_balance_for_interest calculation_method compounding_period interest_basis
69
+ accrual_frequency rounding_rule promotional_start_date promotional_end_date is_active
70
+ created_at updated_at]
71
+ end
72
+
73
+ def self.ransackable_associations(auth_object = nil)
74
+ %w[virtual_account_product interest_rate_type interest_rate_tiers]
75
+ end
76
+
77
+ def interest_free?
78
+ interest_rate_type&.code == "INTEREST_FREE"
79
+ end
80
+
81
+ def fixed_rate?
82
+ interest_rate_type&.code == "FIXED"
83
+ end
84
+
85
+ def variable_rate?
86
+ interest_rate_type&.code == "VARIABLE"
87
+ end
88
+
89
+ def promotional_rate?
90
+ interest_rate_type&.code == "PROMOTIONAL"
91
+ end
92
+
60
93
  private
61
94
 
62
95
  def promotional_dates_consistency
@@ -81,5 +114,81 @@ module Dscf::Banking
81
114
  errors.add(:calculation_day_of_month, "must be specified for annual accrual") if calculation_day_of_month.blank?
82
115
  end
83
116
  end
117
+
118
+ def rate_type_specific_validations
119
+ return if interest_rate_type.blank?
120
+
121
+ case interest_rate_type.code
122
+ when "INTEREST_FREE"
123
+ validate_interest_free
124
+ when "FIXED"
125
+ validate_fixed_rate
126
+ when "VARIABLE"
127
+ validate_variable_rate
128
+ when "PROMOTIONAL"
129
+ validate_promotional_rate
130
+ end
131
+ end
132
+
133
+ def validate_interest_free
134
+ if annual_interest_rate.present? && annual_interest_rate > 0
135
+ errors.add(:annual_interest_rate, "must be 0 for interest-free accounts")
136
+ end
137
+ end
138
+
139
+ def validate_fixed_rate
140
+ if annual_interest_rate.blank? || annual_interest_rate <= 0
141
+ errors.add(:annual_interest_rate, "must be greater than 0 for fixed rate")
142
+ end
143
+ end
144
+
145
+ def validate_variable_rate
146
+ if annual_interest_rate.blank? || annual_interest_rate <= 0
147
+ errors.add(:annual_interest_rate, "must be greater than 0 for variable rate")
148
+ end
149
+ end
150
+
151
+ def validate_promotional_rate
152
+ if promotional_start_date.blank?
153
+ errors.add(:promotional_start_date, "is required for promotional rate")
154
+ end
155
+ if promotional_end_date.blank?
156
+ errors.add(:promotional_end_date, "is required for promotional rate")
157
+ end
158
+ if annual_interest_rate.blank? || annual_interest_rate <= 0
159
+ errors.add(:annual_interest_rate, "must be greater than 0 for promotional rate")
160
+ end
161
+ end
162
+
163
+ def tiers_only_for_variable_rate
164
+ return if interest_rate_type.blank?
165
+ return unless persisted? || interest_rate_tiers.loaded?
166
+
167
+ if !variable_rate? && interest_rate_tiers.any?
168
+ errors.add(:base, "Interest rate tiers can only be used with variable rate type")
169
+ end
170
+ end
171
+
172
+ def interest_rate_type_requirements
173
+ return if interest_rate_type.blank?
174
+ return unless persisted?
175
+
176
+ if variable_rate? && interest_rate_tiers.empty?
177
+ errors.add(:base, "Variable rate type requires at least one interest rate tier")
178
+ end
179
+ end
180
+
181
+ def set_interest_basis_from_accrual_frequency
182
+ return if accrual_frequency.blank?
183
+ return if interest_free?
184
+ return if interest_basis.present?
185
+
186
+ case accrual_frequency
187
+ when "daily"
188
+ self.interest_basis = :actual_365
189
+ when "monthly", "quarterly", "annually"
190
+ self.interest_basis = :thirty_360
191
+ end
192
+ end
84
193
  end
85
194
  end
@@ -19,6 +19,7 @@ module Dscf::Banking
19
19
 
20
20
  has_many :product_approvals, class_name: "Dscf::Banking::ProductApproval", dependent: :destroy
21
21
  has_many :product_audit_logs, class_name: "Dscf::Banking::ProductAuditLog", dependent: :destroy
22
+ has_many :interest_configurations, class_name: "Dscf::Banking::InterestConfiguration", dependent: :destroy
22
23
 
23
24
  validates :product_code, presence: true, uniqueness: { case_sensitive: true }, length: { maximum: 50 }
24
25
  validates :product_name, presence: true, length: { maximum: 200 }
@@ -42,7 +43,7 @@ module Dscf::Banking
42
43
  end
43
44
 
44
45
  def self.ransackable_associations(auth_object = nil)
45
- %w[product_category created_by approved_by reviews]
46
+ %w[product_category created_by approved_by reviews interest_configurations]
46
47
  end
47
48
 
48
49
  before_validation :strip_whitespace
@@ -9,7 +9,7 @@ module Dscf::Banking
9
9
  belongs_to :assigned_branch_manager, optional: true
10
10
  has_one :account, serializer: AccountSerializer, if: :has_account?
11
11
  has_many :reviews, serializer: Dscf::Core::ReviewSerializer
12
- has_many :documents, serializer: Dscf::Banking::DocumentSerializer
12
+ has_many :documents, serializer: DocumentSerializer
13
13
 
14
14
  def has_account?
15
15
  object.has_account?
@@ -1,6 +1,14 @@
1
1
  module Dscf::Banking
2
2
  class DocumentSerializer < ActiveModel::Serializer
3
- attributes :id, :document_type, :is_verified, :verified_at, :metadata, :file_urls, :created_at, :updated_at
3
+ attributes :id, :document_type, :is_verified, :verified_at, :metadata, :file_urls, :created_at, :updated_at,
4
+ :documentable_type, :documentable_id, :documentable
5
+
6
+ def documentable
7
+ {
8
+ type: object.documentable_type,
9
+ id: object.documentable_id
10
+ }
11
+ end
4
12
 
5
13
  def file_urls
6
14
  return [] unless object.files.attached?
@@ -7,5 +7,6 @@ module Dscf::Banking
7
7
 
8
8
  belongs_to :virtual_account_product, serializer: VirtualAccountProductSerializer
9
9
  belongs_to :interest_rate_type, serializer: InterestRateTypeSerializer
10
+ has_many :interest_rate_tiers, serializer: InterestRateTierSerializer
10
11
  end
11
12
  end
data/config/routes.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  Dscf::Banking::Engine.routes.draw do
2
- resources :accounts do
3
- get "full_name", to: "accounts#full_name", on: :member
2
+ resources :accounts do
4
3
  collection do
5
4
  get :me
6
5
  end
@@ -0,0 +1,38 @@
1
+ puts "Seeding Interest Rate Types..."
2
+
3
+ interest_rate_types = [
4
+ {
5
+ code: "INTEREST_FREE",
6
+ name: "Interest Free",
7
+ description: "No interest is earned on the account balance. Suitable for transactional accounts or specific product offerings."
8
+ },
9
+ {
10
+ code: "FIXED",
11
+ name: "Fixed Rate",
12
+ description: "A single flat interest rate applied to the entire account balance. Rate remains constant unless manually updated."
13
+ },
14
+ {
15
+ code: "VARIABLE",
16
+ name: "Variable Rate",
17
+ description: "Tiered interest rates based on balance ranges. Different rates apply to different balance brackets, encouraging higher deposits."
18
+ },
19
+ {
20
+ code: "PROMOTIONAL",
21
+ name: "Promotional Rate",
22
+ description: "Temporary special interest rate applied for a specific period. Automatically reverts to the default rate after the promotional period ends."
23
+ }
24
+ ]
25
+
26
+ interest_rate_types.each do |rate_type_data|
27
+ rate_type = Dscf::Banking::InterestRateType.find_or_initialize_by(code: rate_type_data[:code])
28
+ rate_type.assign_attributes(rate_type_data)
29
+
30
+ if rate_type.save
31
+ puts " ✓ Created/Updated: #{rate_type.name} (#{rate_type.code})"
32
+ else
33
+ puts " ✗ Failed to create #{rate_type_data[:name]}: #{rate_type.errors.full_messages.join(', ')}"
34
+ end
35
+ end
36
+
37
+ puts "Interest Rate Types seeding completed!"
38
+ puts "Total Interest Rate Types: #{Dscf::Banking::InterestRateType.count}"
data/db/seeds.rb CHANGED
@@ -48,6 +48,43 @@ user7 = User.create(name: "Fikirte Alemayehu", email: "fikirte@example.com", pas
48
48
  user7.roles << branch_manager_role
49
49
  puts "Created user: #{user7.name}"
50
50
 
51
+ # Seed Interest Rate Types
52
+ puts "Seeding Interest Rate Types..."
53
+ interest_rate_types = [
54
+ {
55
+ code: "INTEREST_FREE",
56
+ name: "Interest Free",
57
+ description: "No interest is earned on the account balance. Suitable for transactional accounts or specific product offerings."
58
+ },
59
+ {
60
+ code: "FIXED",
61
+ name: "Fixed Rate",
62
+ description: "A single flat interest rate applied to the entire account balance. Rate remains constant unless manually updated."
63
+ },
64
+ {
65
+ code: "VARIABLE",
66
+ name: "Variable Rate",
67
+ description: "Tiered interest rates based on balance ranges. Different rates apply to different balance brackets, encouraging higher deposits."
68
+ },
69
+ {
70
+ code: "PROMOTIONAL",
71
+ name: "Promotional Rate",
72
+ description: "Temporary special interest rate applied for a specific period. Automatically reverts to the default rate after the promotional period ends."
73
+ }
74
+ ]
75
+
76
+ interest_rate_types.each do |rate_type_data|
77
+ rate_type = Dscf::Banking::InterestRateType.find_or_initialize_by(code: rate_type_data[:code])
78
+ rate_type.assign_attributes(rate_type_data)
79
+
80
+ if rate_type.save
81
+ puts " ✓ Created/Updated: #{rate_type.name} (#{rate_type.code})"
82
+ else
83
+ puts " ✗ Failed to create #{rate_type_data[:name]}: #{rate_type.errors.full_messages.join(', ')}"
84
+ end
85
+ end
86
+ puts "Interest Rate Types seeding completed!"
87
+
51
88
  # Seed transaction types
52
89
  puts "Seeding transaction types..."
53
90
  deposit_type = Dscf::Banking::TransactionType.find_or_create_by(code: "DEPOSIT") do |tt|
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Banking
3
- VERSION = "0.3.5"
3
+ VERSION = "0.3.6"
4
4
  end
5
5
  end
@@ -3,34 +3,62 @@ FactoryBot.define do
3
3
  association :virtual_account_product, factory: :virtual_account_product
4
4
  association :interest_rate_type, factory: :interest_rate_type
5
5
 
6
- annual_interest_rate { Faker::Number.decimal(l_digits: 1, r_digits: 4).clamp(0.0001, 1.0) }
7
- income_tax_rate { Faker::Number.decimal(l_digits: 1, r_digits: 4).clamp(0.0, 1.0) }
8
- minimum_balance_for_interest { Faker::Number.decimal(l_digits: 4, r_digits: 2).clamp(0.0, 999999.99) }
9
- calculation_method { [ 0, 1 ].sample }
10
- compounding_period { [ 0, 1, 2, 3, 4 ].sample }
11
- interest_basis { [ 0, 1, 2 ].sample }
12
- accrual_frequency { [ 0, 1, 2, 3, 4 ].sample }
13
- rounding_rule { [ 0, 1, 2 ].sample }
14
- calculation_timing { Faker::Time.between(from: Time.current.beginning_of_day, to: Time.current.end_of_day) }
6
+ annual_interest_rate { 0.05 }
7
+ income_tax_rate { 0.05 }
8
+ minimum_balance_for_interest { 0.0 }
9
+ calculation_method { :simple }
10
+ compounding_period { nil }
11
+ interest_basis { :actual_365 }
12
+ accrual_frequency { :monthly }
13
+ rounding_rule { :nearest_cent }
14
+ calculation_timing { Time.current }
15
15
  is_active { true }
16
16
 
17
17
  trait :inactive do
18
18
  is_active { false }
19
19
  end
20
20
 
21
+ trait :interest_free do
22
+ association :interest_rate_type, factory: [ :interest_rate_type, :interest_free ]
23
+ annual_interest_rate { 0 }
24
+ calculation_method { nil }
25
+ compounding_period { nil }
26
+ interest_basis { nil }
27
+ accrual_frequency { nil }
28
+ rounding_rule { nil }
29
+ calculation_timing { nil }
30
+ end
31
+
32
+ trait :fixed_rate do
33
+ association :interest_rate_type, factory: [ :interest_rate_type, :fixed_rate ]
34
+ annual_interest_rate { 0.05 }
35
+ calculation_method { :simple }
36
+ end
37
+
38
+ trait :variable_rate do
39
+ association :interest_rate_type, factory: [ :interest_rate_type, :variable_rate ]
40
+ annual_interest_rate { 0.03 }
41
+
42
+ after(:create) do |config|
43
+ create_list(:interest_rate_tier, 3, interest_config: config)
44
+ end
45
+ end
46
+
21
47
  trait :promotional do
22
- promotional_start_date { Faker::Date.between(from: 30.days.ago, to: Date.current) }
23
- promotional_end_date { Faker::Date.between(from: Date.current, to: 30.days.from_now) }
48
+ association :interest_rate_type, factory: [ :interest_rate_type, :promotional_rate ]
49
+ promotional_start_date { 30.days.ago.to_date }
50
+ promotional_end_date { 30.days.from_now.to_date }
51
+ annual_interest_rate { 0.08 }
24
52
  end
25
53
 
26
54
  trait :simple_interest do
27
- calculation_method { 0 }
55
+ calculation_method { :simple }
28
56
  compounding_period { nil }
29
57
  end
30
58
 
31
59
  trait :compound_interest do
32
- calculation_method { 1 }
33
- compounding_period { [ 0, 1, 2, 3, 4 ].sample }
60
+ calculation_method { :compound }
61
+ compounding_period { :monthly }
34
62
  end
35
63
  end
36
64
  end
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :interest_rate_type, class: "Dscf::Banking::InterestRateType" do
3
- sequence(:code) { |n| "RATE#{n.to_s.rjust(3, '0')}" }
3
+ sequence(:code) { |n| "RATE_#{n.to_s.rjust(3, '0')}" }
4
4
  sequence(:name) { |n| "Interest Rate Type #{n}" }
5
5
  description { Faker::Lorem.paragraph(sentence_count: 2) }
6
6
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dscf-banking
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eyosiyas Mekbib
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-10-17 00:00:00.000000000 Z
10
+ date: 2025-10-25 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -482,8 +482,6 @@ files:
482
482
  - app/services/dscf/banking/deposit_service.rb
483
483
  - app/services/dscf/banking/transfer_service.rb
484
484
  - app/services/dscf/banking/withdrawal_service.rb
485
- - config/initializers/review_callbacks.rb
486
- - config/initializers/review_extensions.rb
487
485
  - config/locales/en.yml
488
486
  - config/routes.rb
489
487
  - db/migrate/20250830211002_create_dscf_banking_product_categories.rb
@@ -502,6 +500,7 @@ files:
502
500
  - db/migrate/20250919182831_create_dscf_banking_transaction_types.rb
503
501
  - db/migrate/20250919184220_create_dscf_banking_transactions.rb
504
502
  - db/seeds.rb
503
+ - db/seeds/interest_rate_types.rb
505
504
  - lib/dscf/banking.rb
506
505
  - lib/dscf/banking/engine.rb
507
506
  - lib/dscf/banking/version.rb
@@ -1,23 +0,0 @@
1
- Rails.application.config.to_prepare do
2
- ActiveSupport::Notifications.subscribe("review.created") do |name, start, finish, id, payload|
3
- reviewable = payload[:reviewable]
4
-
5
- if reviewable.is_a?(Dscf::Banking::Application)
6
- reviewable.reload
7
- review_status = reviewable.review_status
8
-
9
- status_map = {
10
- "submitted" => "submitted",
11
- "under_review" => "under_review",
12
- "approved" => "approved",
13
- "rejected" => "rejected",
14
- "request_modification" => "request_modification"
15
- }
16
-
17
- mapped_status = status_map[review_status]
18
- if mapped_status && reviewable.status != mapped_status
19
- reviewable.update!(status: mapped_status)
20
- end
21
- end
22
- end
23
- end
@@ -1,36 +0,0 @@
1
- module Dscf::Banking
2
- module ReviewExtensions
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- after_create :sync_application_status, if: -> { reviewable.is_a?(Dscf::Banking::Application) }
7
- end
8
-
9
- private
10
-
11
- def sync_application_status
12
- return unless reviewable.is_a?(Dscf::Banking::Application)
13
-
14
- application = reviewable
15
- review_status = application.review_status
16
-
17
- status_map = {
18
- "submitted" => "submitted",
19
- "under_review" => "under_review",
20
- "approved" => "approved",
21
- "rejected" => "rejected",
22
- "request_modification" => "request_modification"
23
- }
24
-
25
- mapped_status = status_map[review_status]
26
- if mapped_status && application.status != mapped_status
27
- application.update!(status: mapped_status)
28
- end
29
- end
30
- end
31
- end
32
-
33
- # Extend the Dscf::Core::Review model with our extensions
34
- Rails.application.config.to_prepare do
35
- Dscf::Core::Review.include(Dscf::Banking::ReviewExtensions) if defined?(Dscf::Core::Review)
36
- end