dscf-banking 0.2.2 → 0.2.3

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: 15401decf84bf542c773e447b403a9bf49631c9d0a566b81b0301dfddb880ff4
4
- data.tar.gz: 5f5cc744a1fadafbd69fd740167aad3ab668c0aa37951ce8ff0a8842e0881e5c
3
+ metadata.gz: 9fc221b52889b3f647a6bf2aece413c37920cd18b793e15507d0c54d10d64049
4
+ data.tar.gz: 36c852689c3e64245e5b3f36bbd31d54506e04e82fb259329e4c711274ce9e48
5
5
  SHA512:
6
- metadata.gz: 57fbc8692e1d4767bb48be19d29c7ec5350239cbfdaaa18c9ee0349acd43246e83b8a8343d24d0788a9be475a250bce445f3740ffab362e1eb90c438a889a74a
7
- data.tar.gz: 9a5eff19db2c9e2d1379c699a83d7409e339efb92d6bc8f761a92630912bfd58b2881743abc024f3809e2860fc044623dad1e8d53dfaece60670f06af1c986cb
6
+ metadata.gz: 35049ee207d00a654faf0f8bdebf0e24c6cbed1e0534a923814040bd88d667b89e8bb643e7b35ff14555cce633b68d99c0fce786a4a8e2b6ecac0aff06c28cd0
7
+ data.tar.gz: d3d6818202de5b7ecdcfc5a7d33495a0d4040b2c00b8f63b0ed13a45645c7a53852209e960c6cb89770f51578e3893843afd1023fa96e061f74ab769666e58b8
@@ -210,6 +210,7 @@ module Dscf::Banking
210
210
  minimum_balance: account.minimum_balance,
211
211
  currency: account.currency,
212
212
  active: account.active,
213
+ system_account: account.system_account,
213
214
  application_id: account.application_id,
214
215
  virtual_account_product_id: account.virtual_account_product_id,
215
216
  account_properties: account.account_properties,
@@ -231,6 +232,7 @@ module Dscf::Banking
231
232
  :minimum_balance,
232
233
  :currency,
233
234
  :active,
235
+ :system_account,
234
236
  account_properties: {}
235
237
  )
236
238
  end
@@ -49,7 +49,7 @@ module Dscf::Banking
49
49
  end
50
50
 
51
51
  def eager_loaded_associations
52
- [ :user, :virtual_account_product, reviews: { reviewed_by: :user_profile } ]
52
+ [ :user, :virtual_account_product, :documents, reviews: { reviewed_by: :user_profile } ]
53
53
  end
54
54
 
55
55
  def allowed_order_columns
@@ -58,10 +58,10 @@ module Dscf::Banking
58
58
 
59
59
  def default_serializer_includes
60
60
  {
61
- index: [:user, :virtual_account_product, reviews: { reviewed_by: :user_profile }],
62
- show: [:user, :virtual_account_product, :account, reviews: { reviewed_by: :user_profile }],
63
- create: [:reviews],
64
- update: [:user, :virtual_account_product, :account, reviews: { reviewed_by: :user_profile }]
61
+ index: [:user, :virtual_account_product, :documents, reviews: { reviewed_by: :user_profile }],
62
+ show: [:user, :virtual_account_product, :account, :documents, reviews: { reviewed_by: :user_profile }],
63
+ create: [:documents, :reviews],
64
+ update: [:user, :virtual_account_product, :account, :documents, reviews: { reviewed_by: :user_profile }]
65
65
  }
66
66
  end
67
67
  end
@@ -0,0 +1,154 @@
1
+ module Dscf::Banking
2
+ class DocumentsController < ApplicationController
3
+ include Dscf::Core::Common
4
+
5
+ def index
6
+ documents = Dscf::Core::Document.all
7
+
8
+ # Handle nested routes
9
+ if params[:application_id].present?
10
+ documents = documents.where(documentable_type: "Dscf::Banking::Application", documentable_id: params[:application_id])
11
+ end
12
+
13
+ # Filter by documentable type and ID if provided
14
+ if params[:documentable_type].present? && params[:documentable_id].present?
15
+ documents = documents.where(documentable_type: params[:documentable_type], documentable_id: params[:documentable_id])
16
+ end
17
+
18
+ # Filter by document type if provided
19
+ documents = documents.where(document_type: params[:document_type]) if params[:document_type].present?
20
+
21
+ # Apply ordering
22
+ order_column = allowed_order_columns.include?(params[:order_by]) ? params[:order_by] : "created_at"
23
+ order_direction = %w[asc desc].include?(params[:order_direction]) ? params[:order_direction] : "desc"
24
+ documents = documents.order("#{order_column} #{order_direction}")
25
+
26
+ render json: {
27
+ success: true,
28
+ data: documents.map { |document| document_data(document) }
29
+ }
30
+ end
31
+
32
+ def show
33
+ document = Dscf::Core::Document.find(params[:id])
34
+ render json: {
35
+ success: true,
36
+ data: document_data(document)
37
+ }
38
+ rescue ActiveRecord::RecordNotFound
39
+ render json: {
40
+ success: false,
41
+ error: "Document not found"
42
+ }, status: :not_found
43
+ end
44
+
45
+ def create
46
+ document_params = model_params
47
+
48
+ # Handle nested routes - set documentable_type and documentable_id from URL params
49
+ if params[:application_id].present?
50
+ document_params[:documentable_type] = "Dscf::Banking::Application"
51
+ document_params[:documentable_id] = params[:application_id]
52
+ end
53
+
54
+ document = Dscf::Core::Document.new(document_params)
55
+
56
+ if document.save
57
+ render json: {
58
+ success: true,
59
+ data: document_data(document)
60
+ }, status: :created
61
+ else
62
+ render json: {
63
+ success: false,
64
+ error: "Failed to create document",
65
+ errors: document.errors.full_messages
66
+ }, status: :unprocessable_content
67
+ end
68
+ end
69
+
70
+ def update
71
+ document = Dscf::Core::Document.find(params[:id])
72
+
73
+ if document.update(model_params)
74
+ render json: {
75
+ success: true,
76
+ data: document_data(document)
77
+ }
78
+ else
79
+ render json: {
80
+ success: false,
81
+ error: "Failed to update document",
82
+ errors: document.errors.full_messages
83
+ }, status: :unprocessable_content
84
+ end
85
+ rescue ActiveRecord::RecordNotFound
86
+ render json: {
87
+ success: false,
88
+ error: "Document not found"
89
+ }, status: :not_found
90
+ end
91
+
92
+ def destroy
93
+ document = Dscf::Core::Document.find(params[:id])
94
+
95
+ if document.destroy
96
+ render json: {
97
+ success: true,
98
+ message: "Document deleted successfully"
99
+ }
100
+ else
101
+ render json: {
102
+ success: false,
103
+ error: "Failed to delete document"
104
+ }, status: :unprocessable_content
105
+ end
106
+ rescue ActiveRecord::RecordNotFound
107
+ render json: {
108
+ success: false,
109
+ error: "Document not found"
110
+ }, status: :not_found
111
+ end
112
+
113
+ private
114
+
115
+ def document_data(document)
116
+ {
117
+ id: document.id,
118
+ document_type: document.document_type,
119
+ file_url: document.file_url,
120
+ documentable_type: document.documentable_type,
121
+ documentable_id: document.documentable_id,
122
+ verified_by: document.verified_by,
123
+ created_at: document.created_at,
124
+ updated_at: document.updated_at
125
+ }
126
+ rescue => e
127
+ # Handle cases where file_url might fail (e.g., ActiveStorage not set up)
128
+ {
129
+ id: document.id,
130
+ document_type: document.document_type,
131
+ file_url: nil,
132
+ documentable_type: document.documentable_type,
133
+ documentable_id: document.documentable_id,
134
+ verified_by: document.verified_by,
135
+ created_at: document.created_at,
136
+ updated_at: document.updated_at
137
+ }
138
+ end
139
+
140
+ def model_params
141
+ params.require(:document).permit(
142
+ :document_type,
143
+ :documentable_type,
144
+ :documentable_id,
145
+ :verified_by_id,
146
+ :file
147
+ )
148
+ end
149
+
150
+ def allowed_order_columns
151
+ %w[id document_type created_at updated_at]
152
+ end
153
+ end
154
+ end
@@ -2,6 +2,14 @@ module Dscf::Banking
2
2
  class TransactionsController < ApplicationController
3
3
  include Dscf::Core::Common
4
4
 
5
+ rescue_from ActiveRecord::RecordNotFound do |exception|
6
+ render json: {
7
+ success: false,
8
+ error: "Transaction not found",
9
+ errors: ["Transaction with ID #{params[:id]} not found"]
10
+ }, status: :not_found
11
+ end
12
+
5
13
  # Transfer money between accounts (from test cases)
6
14
  def transfer
7
15
  debit_account = Dscf::Banking::Account.find_by(account_number: transfer_params[:debit_account_number])
@@ -8,6 +8,7 @@ module Dscf::Banking
8
8
  belongs_to :assigned_branch_manager, class_name: "Dscf::Core::User", optional: true
9
9
  belongs_to :virtual_account_product, class_name: "Dscf::Banking::VirtualAccountProduct"
10
10
  has_one :account, class_name: "Dscf::Banking::Account"
11
+ has_many :documents, as: :documentable, class_name: "Dscf::Core::Document"
11
12
 
12
13
  validates :application_number, presence: true, uniqueness: true, length: { maximum: 50 }
13
14
  validates :applicant_type, presence: true
@@ -53,7 +54,7 @@ module Dscf::Banking
53
54
  end
54
55
 
55
56
  def self.ransackable_associations(auth_object = nil)
56
- %w[user virtual_account_product account reviews]
57
+ %w[user virtual_account_product account reviews documents]
57
58
  end
58
59
 
59
60
  private
@@ -9,6 +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
13
 
13
14
  def has_account?
14
15
  object.has_account?
@@ -0,0 +1,7 @@
1
+ module Dscf::Banking
2
+ class DocumentSerializer < ActiveModel::Serializer
3
+ attributes :id, :document_type, :file_url, :created_at, :updated_at
4
+
5
+ belongs_to :verified_by, polymorphic: true, optional: true
6
+ end
7
+ end
data/config/routes.rb CHANGED
@@ -28,8 +28,11 @@ Dscf::Banking::Engine.routes.draw do
28
28
  patch :approve
29
29
  patch :reject
30
30
  end
31
+ resources :documents, only: [:index, :create]
31
32
  end
32
33
 
34
+ resources :documents
35
+
33
36
  resources :transaction_types
34
37
 
35
38
  resources :transactions do
data/db/seeds.rb CHANGED
@@ -48,4 +48,30 @@ 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 system accounts for transaction processing
52
+ puts "Seeding system accounts..."
53
+ system_deposit_account = Dscf::Banking::Account.find_or_create_by(
54
+ name: "System Deposit Account",
55
+ system_account: true
56
+ ) do |account|
57
+ account.currency = "ETB"
58
+ account.status = :active
59
+ account.current_balance = 0
60
+ account.available_balance = 0
61
+ account.minimum_balance = 0
62
+ end
63
+ puts "Created system deposit account: #{system_deposit_account.name}"
64
+
65
+ system_withdrawal_account = Dscf::Banking::Account.find_or_create_by(
66
+ name: "System Withdrawal Account",
67
+ system_account: true
68
+ ) do |account|
69
+ account.currency = "ETB"
70
+ account.status = :active
71
+ account.current_balance = 0
72
+ account.available_balance = 0
73
+ account.minimum_balance = 0
74
+ end
75
+ puts "Created system withdrawal account: #{system_withdrawal_account.name}"
76
+
51
77
  puts "Seeding completed successfully."
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Banking
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.3"
4
4
  end
5
5
  end
@@ -0,0 +1,10 @@
1
+ FactoryBot.define do
2
+ factory :dscf_banking_document, class: "Dscf::Core::Document" do
3
+ association :documentable, factory: :application
4
+ document_type { :business_license }
5
+ verified_by { nil }
6
+
7
+ # For file attachment, we can use a simple fixture or skip it in basic tests
8
+ # file { Rack::Test::UploadedFile.new(Rails.root.join('spec', 'fixtures', 'test.pdf'), 'application/pdf') }
9
+ end
10
+ end
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.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eyosiyas Mekbib
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-10-11 00:00:00.000000000 Z
10
+ date: 2025-10-12 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -442,6 +442,7 @@ files:
442
442
  - app/controllers/dscf/banking/accounts_controller.rb
443
443
  - app/controllers/dscf/banking/application_controller.rb
444
444
  - app/controllers/dscf/banking/applications_controller.rb
445
+ - app/controllers/dscf/banking/documents_controller.rb
445
446
  - app/controllers/dscf/banking/interest_configurations_controller.rb
446
447
  - app/controllers/dscf/banking/interest_rate_tiers_controller.rb
447
448
  - app/controllers/dscf/banking/interest_rate_types_controller.rb
@@ -467,6 +468,7 @@ files:
467
468
  - app/models/dscf/banking/virtual_account_product.rb
468
469
  - app/serializers/dscf/banking/account_serializer.rb
469
470
  - app/serializers/dscf/banking/application_serializer.rb
471
+ - app/serializers/dscf/banking/document_serializer.rb
470
472
  - app/serializers/dscf/banking/interest_configuration_serializer.rb
471
473
  - app/serializers/dscf/banking/interest_rate_tier_serializer.rb
472
474
  - app/serializers/dscf/banking/interest_rate_type_serializer.rb
@@ -504,6 +506,7 @@ files:
504
506
  - lib/tasks/dscf/banking_tasks.rake
505
507
  - spec/factories/dscf/banking/accounts.rb
506
508
  - spec/factories/dscf/banking/applications.rb
509
+ - spec/factories/dscf/banking/documents.rb
507
510
  - spec/factories/dscf/banking/interest_configurations.rb
508
511
  - spec/factories/dscf/banking/interest_rate_tiers.rb
509
512
  - spec/factories/dscf/banking/interest_rate_types.rb