dscf-payment 0.1.1
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/payment/application_controller.rb +25 -0
- data/app/controllers/dscf/payment/payment_requests_controller.rb +70 -0
- data/app/controllers/dscf/payment/payments_controller.rb +32 -0
- data/app/jobs/dscf/payment/application_job.rb +6 -0
- data/app/mailers/dscf/payment/application_mailer.rb +8 -0
- data/app/models/dscf/payment/application_record.rb +7 -0
- data/app/models/dscf/payment/payment.rb +39 -0
- data/app/models/dscf/payment/payment_request.rb +64 -0
- data/app/serializers/dscf/payment/payment_request_serializer.rb +18 -0
- data/app/serializers/dscf/payment/payment_serializer.rb +16 -0
- data/app/services/dscf/payment/banking_integration_service.rb +37 -0
- data/app/services/dscf/payment/credit_integration_service.rb +56 -0
- data/app/services/dscf/payment/payment_service.rb +128 -0
- data/app/services/dscf/payment/settlement_account_service.rb +37 -0
- data/config/locales/en.yml +21 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20251002191758_create_dscf_payment_payment_requests.rb +32 -0
- data/db/migrate/20251002191802_create_dscf_payment_payments.rb +24 -0
- data/db/migrate/20251003005136_make_payment_request_accounts_optional.rb +6 -0
- data/lib/dscf/payment/engine.rb +31 -0
- data/lib/dscf/payment/errors.rb +10 -0
- data/lib/dscf/payment/version.rb +5 -0
- data/lib/dscf/payment.rb +8 -0
- data/lib/tasks/dscf/payment_tasks.rake +4 -0
- data/spec/factories/dscf/payment/payment_requests.rb +56 -0
- data/spec/factories/dscf/payment/payments.rb +37 -0
- metadata +512 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class CreateDscfPaymentPaymentRequests < ActiveRecord::Migration[8.0]
|
2
|
+
def change
|
3
|
+
create_table :dscf_payment_payment_requests do |t|
|
4
|
+
t.string :payment_type, null: false
|
5
|
+
t.references :from_account, null: false, foreign_key: { to_table: :dscf_banking_accounts }
|
6
|
+
t.references :to_account, null: false, foreign_key: { to_table: :dscf_banking_accounts }
|
7
|
+
t.decimal :amount, precision: 15, scale: 2, null: false
|
8
|
+
t.string :currency, default: "ETB"
|
9
|
+
t.string :status, default: "pending"
|
10
|
+
t.string :reference_number, null: false
|
11
|
+
t.text :description
|
12
|
+
t.jsonb :metadata, default: {}
|
13
|
+
t.references :payable, polymorphic: true
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
add_index :dscf_payment_payment_requests, :reference_number,
|
19
|
+
unique: true,
|
20
|
+
name: "reference_number_on_dscf_payment_payment_requests_indx"
|
21
|
+
add_index :dscf_payment_payment_requests, :payment_type,
|
22
|
+
name: "payment_type_on_dscf_payment_payment_requests_indx"
|
23
|
+
add_index :dscf_payment_payment_requests, :status,
|
24
|
+
name: "status_on_dscf_payment_payment_requests_indx"
|
25
|
+
add_index :dscf_payment_payment_requests, :from_account_id,
|
26
|
+
name: "from_account_id_on_dscf_payment_payment_requests_indx"
|
27
|
+
add_index :dscf_payment_payment_requests, :to_account_id,
|
28
|
+
name: "to_account_id_on_dscf_payment_payment_requests_indx"
|
29
|
+
add_index :dscf_payment_payment_requests, [ :payable_type, :payable_id ],
|
30
|
+
name: "payable_on_dscf_payment_payment_requests_indx"
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class CreateDscfPaymentPayments < ActiveRecord::Migration[8.0]
|
2
|
+
def change
|
3
|
+
create_table :dscf_payment_payments do |t|
|
4
|
+
t.references :payment_request, null: false, foreign_key: { to_table: :dscf_payment_payment_requests }
|
5
|
+
t.string :transaction_reference, null: false
|
6
|
+
t.decimal :amount, precision: 15, scale: 2, null: false
|
7
|
+
t.string :currency, default: "ETB"
|
8
|
+
t.string :status, default: "pending"
|
9
|
+
t.datetime :processed_at
|
10
|
+
t.text :failure_reason
|
11
|
+
t.references :banking_transaction, foreign_key: { to_table: :dscf_banking_transactions }
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :dscf_payment_payments, :transaction_reference,
|
17
|
+
unique: true,
|
18
|
+
name: "transaction_reference_on_dscf_payment_payments_indx"
|
19
|
+
add_index :dscf_payment_payments, :status,
|
20
|
+
name: "status_on_dscf_payment_payments_indx"
|
21
|
+
add_index :dscf_payment_payments, :processed_at,
|
22
|
+
name: "processed_at_on_dscf_payment_payments_indx"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "dscf/payment/errors"
|
2
|
+
|
3
|
+
module Dscf
|
4
|
+
module Payment
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
isolate_namespace Dscf::Payment
|
7
|
+
config.generators.api_only = true
|
8
|
+
|
9
|
+
# Load dependent engines and their migrations for testing
|
10
|
+
initializer :load_dependent_engines do
|
11
|
+
require "dscf/core"
|
12
|
+
require "dscf/banking"
|
13
|
+
require "dscf/credit"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Ensure dependent engine migrations are available in test environment
|
17
|
+
initializer :append_dependent_migrations, after: :load_dependent_engines do |app|
|
18
|
+
# Append migrations from dependent engines
|
19
|
+
if defined?(Dscf::Core::Engine)
|
20
|
+
app.config.paths["db/migrate"].concat(Dscf::Core::Engine.config.paths["db/migrate"].expanded)
|
21
|
+
end
|
22
|
+
if defined?(Dscf::Banking::Engine)
|
23
|
+
app.config.paths["db/migrate"].concat(Dscf::Banking::Engine.config.paths["db/migrate"].expanded)
|
24
|
+
end
|
25
|
+
if defined?(Dscf::Credit::Engine)
|
26
|
+
app.config.paths["db/migrate"].concat(Dscf::Credit::Engine.config.paths["db/migrate"].expanded)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Dscf::Payment
|
2
|
+
class PaymentError < StandardError; end
|
3
|
+
class InsufficientFundsError < PaymentError; end
|
4
|
+
class AccountNotActiveError < PaymentError; end
|
5
|
+
class InvalidPaymentTypeError < PaymentError; end
|
6
|
+
class InvalidAmountError < PaymentError; end
|
7
|
+
class SettlementAccountError < PaymentError; end
|
8
|
+
class BankingTransactionError < PaymentError; end
|
9
|
+
class CreditOperationError < PaymentError; end
|
10
|
+
end
|
data/lib/dscf/payment.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :dscf_payment_payment_request, class: "Dscf::Payment::PaymentRequest" do
|
3
|
+
association :from_account, factory: :dscf_banking_account
|
4
|
+
association :to_account, factory: :dscf_banking_account
|
5
|
+
|
6
|
+
payment_type { "transfer" }
|
7
|
+
amount { 1000.00 }
|
8
|
+
currency { "ETB" }
|
9
|
+
status { "pending" }
|
10
|
+
description { "Test payment request" }
|
11
|
+
metadata { {} }
|
12
|
+
|
13
|
+
trait :disbursement do
|
14
|
+
payment_type { "disbursement" }
|
15
|
+
# Add associations for disbursement-specific data
|
16
|
+
end
|
17
|
+
|
18
|
+
trait :transfer do
|
19
|
+
payment_type { "transfer" }
|
20
|
+
end
|
21
|
+
|
22
|
+
trait :repayment do
|
23
|
+
payment_type { "repayment" }
|
24
|
+
# Add associations for repayment-specific data
|
25
|
+
end
|
26
|
+
|
27
|
+
trait :approved do
|
28
|
+
status { "approved" }
|
29
|
+
end
|
30
|
+
|
31
|
+
trait :processing do
|
32
|
+
status { "processing" }
|
33
|
+
end
|
34
|
+
|
35
|
+
trait :completed do
|
36
|
+
status { "completed" }
|
37
|
+
end
|
38
|
+
|
39
|
+
trait :failed do
|
40
|
+
status { "failed" }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Alias for shared spec compatibility
|
45
|
+
factory :payment_request, class: "Dscf::Payment::PaymentRequest" do
|
46
|
+
association :from_account, factory: :dscf_banking_account
|
47
|
+
association :to_account, factory: :dscf_banking_account
|
48
|
+
|
49
|
+
payment_type { "transfer" }
|
50
|
+
amount { 1000.00 }
|
51
|
+
currency { "ETB" }
|
52
|
+
status { "pending" }
|
53
|
+
description { "Test payment request" }
|
54
|
+
metadata { {} }
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :dscf_payment_payment, class: "Dscf::Payment::Payment" do
|
3
|
+
association :payment_request, factory: :dscf_payment_payment_request
|
4
|
+
|
5
|
+
amount { 1000.00 }
|
6
|
+
currency { "ETB" }
|
7
|
+
status { "pending" }
|
8
|
+
|
9
|
+
trait :processing do
|
10
|
+
status { "processing" }
|
11
|
+
end
|
12
|
+
|
13
|
+
trait :completed do
|
14
|
+
status { "completed" }
|
15
|
+
processed_at { Time.current }
|
16
|
+
end
|
17
|
+
|
18
|
+
trait :failed do
|
19
|
+
status { "failed" }
|
20
|
+
failure_reason { "Test failure reason" }
|
21
|
+
processed_at { Time.current }
|
22
|
+
end
|
23
|
+
|
24
|
+
trait :with_banking_transaction do
|
25
|
+
association :banking_transaction, factory: :dscf_banking_transaction
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Alias for shared spec compatibility
|
30
|
+
factory :payment, class: "Dscf::Payment::Payment" do
|
31
|
+
association :payment_request, factory: :dscf_payment_payment_request
|
32
|
+
|
33
|
+
amount { 1000.00 }
|
34
|
+
currency { "ETB" }
|
35
|
+
status { "pending" }
|
36
|
+
end
|
37
|
+
end
|