forest_admin_datasource_mambu_payments 1.33.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/.rspec +3 -0
- data/Rakefile +6 -0
- data/forest_admin_datasource_mambu_payments.gemspec +37 -0
- data/lib/forest_admin_datasource_mambu_payments/client/reads.rb +66 -0
- data/lib/forest_admin_datasource_mambu_payments/client/writes.rb +42 -0
- data/lib/forest_admin_datasource_mambu_payments/client.rb +166 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/account_holder.rb +64 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/balance.rb +75 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/base_collection.rb +254 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/claim.rb +98 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/connected_account.rb +103 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/direct_debit_mandate.rb +125 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/event.rb +133 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/expected_payment.rb +132 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/external_account.rb +121 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/file.rb +89 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/incoming_payment.rb +120 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/internal_account.rb +136 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/payee_verification_request.rb +88 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/payment_capture.rb +136 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/payment_order.rb +132 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/reconciliation.rb +93 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/return.rb +132 -0
- data/lib/forest_admin_datasource_mambu_payments/collections/transaction.rb +113 -0
- data/lib/forest_admin_datasource_mambu_payments/configuration.rb +36 -0
- data/lib/forest_admin_datasource_mambu_payments/datasource.rb +35 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/disable_search.rb +31 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/helpers.rb +94 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/messages.rb +30 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/holder_link_plugin.rb +56 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_account_holder_to_direct_debit_mandates.rb +14 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_account_holder_to_incoming_payments.rb +14 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_external_account_to_direct_debit_mandates.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_external_account_to_incoming_payments.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_external_account_to_payment_orders.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_incoming_payment_to_events.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_incoming_payment_to_expected_payments.rb +21 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_incoming_payment_to_returns.rb +12 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_incoming_payment_to_transactions.rb +20 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_internal_account_to_balances.rb +17 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_internal_account_to_incoming_payments.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_internal_account_to_payment_orders.rb +17 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_payment_order_to_events.rb +13 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_payment_order_to_receiving_account_holder.rb +15 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_payment_order_to_returns.rb +12 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/link_payment_order_to_transactions.rb +51 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/one_to_many_link_plugin.rb +35 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/pivot_resolution.rb +73 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/two_step_connected_account_filter.rb +38 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/two_step_cross_reconciliation_filter.rb +55 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/two_step_holder_filter.rb +32 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/two_step_link_plugin.rb +64 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/relations/two_step_reconciliation_filter.rb +39 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/approve_payment_order.rb +56 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/cancel_payment_order.rb +66 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/create_account_holder.rb +44 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/create_external_account.rb +54 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/create_internal_account.rb +58 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/create_payment_order.rb +66 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/trigger_payee_verification.rb +58 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/update_account_holder.rb +67 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/update_external_account.rb +75 -0
- data/lib/forest_admin_datasource_mambu_payments/plugins/smart_actions/update_internal_account.rb +75 -0
- data/lib/forest_admin_datasource_mambu_payments/query/condition_tree_translator.rb +115 -0
- data/lib/forest_admin_datasource_mambu_payments/version.rb +3 -0
- data/lib/forest_admin_datasource_mambu_payments.rb +44 -0
- metadata +170 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class InternalAccount < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
client_resource :internal_account
|
|
8
|
+
|
|
9
|
+
def initialize(datasource)
|
|
10
|
+
super(datasource, 'MambuInternalAccount')
|
|
11
|
+
define_schema
|
|
12
|
+
define_relations
|
|
13
|
+
reconcile_filter_operators!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create(_caller, data)
|
|
17
|
+
serialize(datasource.client.create_internal_account(build_payload(data)))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update(caller, filter, patch)
|
|
21
|
+
payload = build_payload(patch)
|
|
22
|
+
ids_for(caller, filter).each { |id| datasource.client.update_internal_account(id, payload) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def delete(caller, filter)
|
|
26
|
+
ids_for(caller, filter).each { |id| datasource.client.delete_internal_account(id) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def serialize(record)
|
|
30
|
+
a = attrs_of(record)
|
|
31
|
+
{
|
|
32
|
+
'id' => a['id'],
|
|
33
|
+
'object' => a['object'],
|
|
34
|
+
'status' => a['status'],
|
|
35
|
+
'status_details' => a['status_details'],
|
|
36
|
+
'type' => a['type'],
|
|
37
|
+
'name' => a['name'],
|
|
38
|
+
'holder_name' => a['holder_name'],
|
|
39
|
+
'alternative_holder_names' => a['alternative_holder_names'],
|
|
40
|
+
'connected_account_ids' => a['connected_account_ids'],
|
|
41
|
+
'account_number' => a['account_number'],
|
|
42
|
+
'account_number_format' => a['account_number_format'],
|
|
43
|
+
'bank_code' => a['bank_code'],
|
|
44
|
+
'bank_name' => a['bank_name'],
|
|
45
|
+
'bank_address' => a['bank_address'],
|
|
46
|
+
'bank_code_format' => a['bank_code_format'],
|
|
47
|
+
'holder_address' => a['holder_address'],
|
|
48
|
+
'account_holder_id' => a['account_holder_id'],
|
|
49
|
+
'creditor_identifier' => a['creditor_identifier'],
|
|
50
|
+
'organization_identification' => a['organization_identification'],
|
|
51
|
+
'customer_bic' => a['customer_bic'],
|
|
52
|
+
'distinguished_name' => a['distinguished_name'],
|
|
53
|
+
'currencies' => a['currencies'],
|
|
54
|
+
'cbs_source' => a['cbs_source'],
|
|
55
|
+
'cbs_account_id' => a['cbs_account_id'],
|
|
56
|
+
'cbs_account_type' => a['cbs_account_type'],
|
|
57
|
+
'synchronized_with_bank' => a['synchronized_with_bank'],
|
|
58
|
+
'metadata' => a['metadata'],
|
|
59
|
+
'bank_data' => a['bank_data'],
|
|
60
|
+
'custom_fields' => a['custom_fields'],
|
|
61
|
+
'created_at' => a['created_at']
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
|
|
67
|
+
def collection_filters
|
|
68
|
+
{
|
|
69
|
+
'account_holder_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def many_to_one_embeds
|
|
74
|
+
[
|
|
75
|
+
{ foreign_key: 'account_holder_id', relation_name: 'account_holder',
|
|
76
|
+
collection: 'MambuAccountHolder' }
|
|
77
|
+
]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def define_schema
|
|
83
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
84
|
+
is_read_only: true, is_sortable: true))
|
|
85
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
86
|
+
add_field('status', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
87
|
+
add_field('status_details', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
88
|
+
add_field('type', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
89
|
+
add_field('name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
90
|
+
add_field('holder_name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
91
|
+
add_field('alternative_holder_names', ColumnSchema.new(column_type: 'Json', is_read_only: false,
|
|
92
|
+
is_sortable: false))
|
|
93
|
+
add_field('connected_account_ids', ColumnSchema.new(column_type: 'Json', is_read_only: false,
|
|
94
|
+
is_sortable: false))
|
|
95
|
+
add_field('account_number', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
96
|
+
add_field('account_number_format', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
97
|
+
is_sortable: false))
|
|
98
|
+
add_field('bank_code', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
99
|
+
add_field('bank_name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
100
|
+
add_field('bank_address', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
101
|
+
add_field('bank_code_format', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
102
|
+
is_sortable: false))
|
|
103
|
+
add_field('holder_address', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
104
|
+
add_field('account_holder_id', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
105
|
+
is_sortable: true))
|
|
106
|
+
add_field('creditor_identifier', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
107
|
+
is_sortable: false))
|
|
108
|
+
add_field('organization_identification', ColumnSchema.new(column_type: 'Json', is_read_only: false,
|
|
109
|
+
is_sortable: false))
|
|
110
|
+
add_field('customer_bic', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
111
|
+
add_field('distinguished_name', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
112
|
+
is_sortable: false))
|
|
113
|
+
add_field('currencies', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
114
|
+
add_field('cbs_source', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
115
|
+
add_field('cbs_account_id', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
116
|
+
add_field('cbs_account_type', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
117
|
+
is_sortable: false))
|
|
118
|
+
add_field('synchronized_with_bank', ColumnSchema.new(column_type: 'Boolean', is_read_only: false,
|
|
119
|
+
is_sortable: false))
|
|
120
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
121
|
+
add_field('bank_data', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
122
|
+
add_field('custom_fields', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
123
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def define_relations
|
|
127
|
+
add_field('account_holder', ManyToOneSchema.new(
|
|
128
|
+
foreign_collection: 'MambuAccountHolder',
|
|
129
|
+
foreign_key: 'account_holder_id',
|
|
130
|
+
foreign_key_target: 'id'
|
|
131
|
+
))
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module ForestAdminDatasourceMambuPayments
|
|
2
|
+
module Collections
|
|
3
|
+
# Payee Verification Requests are emitted by Numeral when an outgoing
|
|
4
|
+
# verification is sent (via the `Trigger payee verification` smart
|
|
5
|
+
# action on external accounts) or when an incoming verification arrives
|
|
6
|
+
# from the network. From Forest's perspective they are read-only: send
|
|
7
|
+
# and simulate are lifecycle operations exposed as smart-action plugins
|
|
8
|
+
# (see TriggerPayeeVerification) rather than collection writes.
|
|
9
|
+
class PayeeVerificationRequest < BaseCollection
|
|
10
|
+
ENUM_STATUS = %w[completed failed].freeze
|
|
11
|
+
ENUM_FAILURE_CODE = %w[business_error technical_error psp_technical_error].freeze
|
|
12
|
+
ENUM_DIRECTION = %w[outgoing incoming].freeze
|
|
13
|
+
ENUM_SCHEME = %w[vop].freeze
|
|
14
|
+
ENUM_MATCHING_RESULT = %w[match close_match no_match impossible_match].freeze
|
|
15
|
+
|
|
16
|
+
client_resource :payee_verification_request
|
|
17
|
+
|
|
18
|
+
def initialize(datasource)
|
|
19
|
+
super(datasource, 'MambuPayeeVerificationRequest')
|
|
20
|
+
define_schema
|
|
21
|
+
reconcile_filter_operators!
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def serialize(record)
|
|
25
|
+
a = attrs_of(record)
|
|
26
|
+
{
|
|
27
|
+
'id' => a['id'],
|
|
28
|
+
'object' => a['object'],
|
|
29
|
+
'status' => a['status'],
|
|
30
|
+
'failure_code' => a['failure_code'],
|
|
31
|
+
'status_details' => a['status_details'],
|
|
32
|
+
'direction' => a['direction'],
|
|
33
|
+
'scheme' => a['scheme'],
|
|
34
|
+
'request' => a['request'],
|
|
35
|
+
'matching_result' => a['matching_result'],
|
|
36
|
+
'payee_suggested_name' => a['payee_suggested_name'],
|
|
37
|
+
'matching_details' => a['matching_details'],
|
|
38
|
+
'scheme_data' => a['scheme_data'],
|
|
39
|
+
'metadata' => a['metadata'],
|
|
40
|
+
'response_received_at' => a['response_received_at'],
|
|
41
|
+
'created_at' => a['created_at']
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def collection_filters
|
|
48
|
+
{
|
|
49
|
+
'status' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
50
|
+
'direction' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
51
|
+
'scheme' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
52
|
+
'matching_result' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def define_schema
|
|
59
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
60
|
+
is_read_only: true, is_sortable: true))
|
|
61
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
62
|
+
add_field('status', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_STATUS,
|
|
63
|
+
is_read_only: true, is_sortable: true))
|
|
64
|
+
add_field('failure_code', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_FAILURE_CODE,
|
|
65
|
+
is_read_only: true, is_sortable: false))
|
|
66
|
+
add_field('status_details', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
67
|
+
add_field('direction', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_DIRECTION,
|
|
68
|
+
is_read_only: true, is_sortable: true))
|
|
69
|
+
add_field('scheme', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_SCHEME,
|
|
70
|
+
is_read_only: true, is_sortable: true))
|
|
71
|
+
# request, matching_details, scheme_data are nested objects with their
|
|
72
|
+
# own sub-fields (payee_identification, scheme_request_id, ...). Forest
|
|
73
|
+
# can't model nested columns natively, so we expose them as Json
|
|
74
|
+
# snapshots — matches how IncomingPayment handles originating_account.
|
|
75
|
+
add_field('request', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
76
|
+
add_field('matching_result', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_MATCHING_RESULT,
|
|
77
|
+
is_read_only: true, is_sortable: true))
|
|
78
|
+
add_field('payee_suggested_name', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
79
|
+
is_sortable: false))
|
|
80
|
+
add_field('matching_details', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
81
|
+
add_field('scheme_data', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
82
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
83
|
+
add_field('response_received_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
84
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class PaymentCapture < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
ENUM_TYPE = %w[charge chargeback refund].freeze
|
|
8
|
+
ENUM_SOURCE = %w[api reporting_file].freeze
|
|
9
|
+
ENUM_RECONCILIATION_STATUS = %w[unreconciled reconciled partially_reconciled].freeze
|
|
10
|
+
|
|
11
|
+
client_resource :payment_capture
|
|
12
|
+
|
|
13
|
+
def initialize(datasource)
|
|
14
|
+
super(datasource, 'MambuPaymentCapture')
|
|
15
|
+
define_schema
|
|
16
|
+
define_relations
|
|
17
|
+
reconcile_filter_operators!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize(record)
|
|
21
|
+
a = attrs_of(record)
|
|
22
|
+
{
|
|
23
|
+
'id' => a['id'],
|
|
24
|
+
'object' => a['object'],
|
|
25
|
+
'idempotency_key' => a['idempotency_key'],
|
|
26
|
+
'connected_account_id' => a['connected_account_id'],
|
|
27
|
+
'type' => a['type'],
|
|
28
|
+
'source' => a['source'],
|
|
29
|
+
'amount' => a['amount'],
|
|
30
|
+
'original_payment_amount' => a['original_payment_amount'],
|
|
31
|
+
'currency' => a['currency'],
|
|
32
|
+
'date' => a['date'],
|
|
33
|
+
'value_date' => a['value_date'],
|
|
34
|
+
'remittance_date' => a['remittance_date'],
|
|
35
|
+
'remittance_reference' => a['remittance_reference'],
|
|
36
|
+
'transaction_reference' => a['transaction_reference'],
|
|
37
|
+
'authorization_id' => a['authorization_id'],
|
|
38
|
+
'payment_reference' => a['payment_reference'],
|
|
39
|
+
'network' => a['network'],
|
|
40
|
+
'merchant_id' => a['merchant_id'],
|
|
41
|
+
'fee_amount' => a['fee_amount'],
|
|
42
|
+
'fee_amount_currency' => a['fee_amount_currency'],
|
|
43
|
+
'net_amount' => a['net_amount'],
|
|
44
|
+
'net_amount_currency' => a['net_amount_currency'],
|
|
45
|
+
'reconciliation_status' => a['reconciliation_status'],
|
|
46
|
+
'reconciled_amount' => a['reconciled_amount'],
|
|
47
|
+
'cbs_data' => a['cbs_data'],
|
|
48
|
+
'lending' => a['lending'],
|
|
49
|
+
'metadata' => a['metadata'],
|
|
50
|
+
'canceled_at' => a['canceled_at'],
|
|
51
|
+
'updated_at' => a['updated_at'],
|
|
52
|
+
'created_at' => a['created_at']
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
protected
|
|
57
|
+
|
|
58
|
+
def collection_filters
|
|
59
|
+
{
|
|
60
|
+
'connected_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
61
|
+
'type' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
62
|
+
'source' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
63
|
+
'reconciliation_status' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def many_to_one_embeds
|
|
68
|
+
[
|
|
69
|
+
{ foreign_key: 'connected_account_id', relation_name: 'connected_account',
|
|
70
|
+
collection: 'MambuConnectedAccount' }
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
# Payment captures are emitted by PSPs (or registered manually via API
|
|
77
|
+
# to reconcile reporting files). From Forest's perspective they're
|
|
78
|
+
# read-only: create / update / cancel exist on the Numeral API but are
|
|
79
|
+
# lifecycle operations better expressed as smart-action plugins later
|
|
80
|
+
# (same approach as payment_orders' approve/cancel).
|
|
81
|
+
def define_schema
|
|
82
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
83
|
+
is_read_only: true, is_sortable: true))
|
|
84
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
85
|
+
add_field('idempotency_key', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
86
|
+
add_field('connected_account_id', ColumnSchema.new(column_type: 'String',
|
|
87
|
+
is_read_only: true, is_sortable: true))
|
|
88
|
+
add_field('type', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_TYPE,
|
|
89
|
+
is_read_only: true, is_sortable: true))
|
|
90
|
+
add_field('source', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_SOURCE,
|
|
91
|
+
is_read_only: true, is_sortable: true))
|
|
92
|
+
add_field('amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
93
|
+
add_field('original_payment_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true,
|
|
94
|
+
is_sortable: false))
|
|
95
|
+
add_field('currency', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
96
|
+
add_field('date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
97
|
+
add_field('value_date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
98
|
+
add_field('remittance_date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
99
|
+
add_field('remittance_reference', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
100
|
+
is_sortable: false))
|
|
101
|
+
add_field('transaction_reference', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
102
|
+
is_sortable: false))
|
|
103
|
+
add_field('authorization_id', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
104
|
+
add_field('payment_reference', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
105
|
+
is_sortable: false))
|
|
106
|
+
add_field('network', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
107
|
+
add_field('merchant_id', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
108
|
+
add_field('fee_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
109
|
+
add_field('fee_amount_currency', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
110
|
+
is_sortable: false))
|
|
111
|
+
add_field('net_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
112
|
+
add_field('net_amount_currency', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
113
|
+
is_sortable: false))
|
|
114
|
+
add_field('reconciliation_status', ColumnSchema.new(column_type: 'Enum',
|
|
115
|
+
enum_values: ENUM_RECONCILIATION_STATUS,
|
|
116
|
+
is_read_only: true, is_sortable: true))
|
|
117
|
+
add_field('reconciled_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
118
|
+
add_field('cbs_data', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
119
|
+
add_field('lending', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
120
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
121
|
+
add_field('canceled_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
122
|
+
add_field('updated_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
123
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def define_relations
|
|
127
|
+
add_field('connected_account', ManyToOneSchema.new(
|
|
128
|
+
foreign_collection: 'MambuConnectedAccount',
|
|
129
|
+
foreign_key: 'connected_account_id',
|
|
130
|
+
foreign_key_target: 'id'
|
|
131
|
+
))
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class PaymentOrder < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
ENUM_DIRECTION = %w[debit credit].freeze
|
|
8
|
+
|
|
9
|
+
client_resource :payment_order
|
|
10
|
+
|
|
11
|
+
def initialize(datasource)
|
|
12
|
+
super(datasource, 'MambuPaymentOrder')
|
|
13
|
+
define_schema
|
|
14
|
+
define_relations
|
|
15
|
+
reconcile_filter_operators!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create(_caller, data)
|
|
19
|
+
serialize(datasource.client.create_payment_order(build_payload(data)))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update(caller, filter, patch)
|
|
23
|
+
payload = build_payload(patch)
|
|
24
|
+
ids_for(caller, filter).each { |id| datasource.client.update_payment_order(id, payload) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete(caller, filter)
|
|
28
|
+
ids_for(caller, filter).each { |id| datasource.client.delete_payment_order(id) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def serialize(record)
|
|
32
|
+
a = attrs_of(record)
|
|
33
|
+
{
|
|
34
|
+
'id' => a['id'],
|
|
35
|
+
'connected_account_id' => a['connected_account_id'],
|
|
36
|
+
'receiving_account_id' => a['receiving_account_id'],
|
|
37
|
+
'type' => a['type'],
|
|
38
|
+
'direction' => a['direction'],
|
|
39
|
+
'status' => a['status'],
|
|
40
|
+
'amount' => a['amount'],
|
|
41
|
+
'currency' => a['currency'],
|
|
42
|
+
'reference' => a['reference'],
|
|
43
|
+
'purpose' => a['purpose'],
|
|
44
|
+
'end_to_end_id' => a['end_to_end_id'],
|
|
45
|
+
'idempotency_key' => a['idempotency_key'],
|
|
46
|
+
'requested_execution_date' => a['requested_execution_date'],
|
|
47
|
+
'value_date' => a['value_date'],
|
|
48
|
+
'initiated_at' => a['initiated_at'],
|
|
49
|
+
'reconciliation_status' => a['reconciliation_status'],
|
|
50
|
+
'reconciled_amount' => a['reconciled_amount'],
|
|
51
|
+
'originating_account' => a['originating_account'],
|
|
52
|
+
'receiving_account' => a['receiving_account'],
|
|
53
|
+
'metadata' => a['metadata'],
|
|
54
|
+
'custom_fields' => a['custom_fields'],
|
|
55
|
+
'created_at' => a['created_at']
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
protected
|
|
60
|
+
|
|
61
|
+
# NOTE: server-side filters verified against Numeral's `GET /payment_orders` docs.
|
|
62
|
+
# Add new entries here (status, direction, currency, created_at ranges, …) as
|
|
63
|
+
# we confirm them — anything not declared raises a clear error rather than
|
|
64
|
+
# silently returning unfiltered results.
|
|
65
|
+
def collection_filters
|
|
66
|
+
{
|
|
67
|
+
'connected_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
68
|
+
# Numeral's list endpoint exposes the receiving external account
|
|
69
|
+
# under the `external_account_id` query param.
|
|
70
|
+
'receiving_account_id' => { ops: [Operators::EQUAL, Operators::IN],
|
|
71
|
+
param: 'external_account_id' }
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def many_to_one_embeds
|
|
76
|
+
[
|
|
77
|
+
{ foreign_key: 'connected_account_id', relation_name: 'connected_account',
|
|
78
|
+
collection: 'MambuConnectedAccount' },
|
|
79
|
+
{ foreign_key: 'receiving_account_id', relation_name: 'external_account',
|
|
80
|
+
collection: 'MambuExternalAccount' }
|
|
81
|
+
]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def define_schema
|
|
87
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
88
|
+
is_read_only: true, is_sortable: true))
|
|
89
|
+
add_field('connected_account_id', ColumnSchema.new(column_type: 'String',
|
|
90
|
+
is_read_only: false, is_sortable: true))
|
|
91
|
+
add_field('receiving_account_id', ColumnSchema.new(column_type: 'String',
|
|
92
|
+
is_read_only: true, is_sortable: true))
|
|
93
|
+
add_field('type', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
94
|
+
add_field('direction', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_DIRECTION,
|
|
95
|
+
is_read_only: false, is_sortable: false))
|
|
96
|
+
add_field('status', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
97
|
+
add_field('amount', ColumnSchema.new(column_type: 'Number', is_read_only: false, is_sortable: false))
|
|
98
|
+
add_field('currency', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
99
|
+
add_field('reference', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
100
|
+
add_field('purpose', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
101
|
+
add_field('end_to_end_id', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
102
|
+
add_field('idempotency_key', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
103
|
+
add_field('requested_execution_date', ColumnSchema.new(column_type: 'Date', is_read_only: false,
|
|
104
|
+
is_sortable: true))
|
|
105
|
+
add_field('value_date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
106
|
+
add_field('initiated_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
107
|
+
add_field('reconciliation_status', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
108
|
+
is_sortable: false))
|
|
109
|
+
add_field('reconciled_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
110
|
+
add_field('originating_account', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
111
|
+
add_field('receiving_account', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
112
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
113
|
+
add_field('custom_fields', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
114
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def define_relations
|
|
118
|
+
add_field('connected_account', ManyToOneSchema.new(
|
|
119
|
+
foreign_collection: 'MambuConnectedAccount',
|
|
120
|
+
foreign_key: 'connected_account_id',
|
|
121
|
+
foreign_key_target: 'id'
|
|
122
|
+
))
|
|
123
|
+
add_field('external_account', ManyToOneSchema.new(
|
|
124
|
+
foreign_collection: 'MambuExternalAccount',
|
|
125
|
+
foreign_key: 'receiving_account_id',
|
|
126
|
+
foreign_key_target: 'id'
|
|
127
|
+
))
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module ForestAdminDatasourceMambuPayments
|
|
2
|
+
module Collections
|
|
3
|
+
class Reconciliation < BaseCollection
|
|
4
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
5
|
+
|
|
6
|
+
ENUM_MATCH_TYPE = %w[manual auto].freeze
|
|
7
|
+
ENUM_PAYMENT_TYPE = %w[payment_order incoming_payment return expected_payment payment_capture].freeze
|
|
8
|
+
|
|
9
|
+
client_resource :reconciliation
|
|
10
|
+
|
|
11
|
+
def initialize(datasource)
|
|
12
|
+
super(datasource, 'MambuReconciliation')
|
|
13
|
+
define_schema
|
|
14
|
+
define_relations
|
|
15
|
+
reconcile_filter_operators!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create(_caller, data)
|
|
19
|
+
serialize(datasource.client.create_reconciliation(build_payload(data)))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update(caller, filter, patch)
|
|
23
|
+
payload = build_payload(patch)
|
|
24
|
+
ids_for(caller, filter).each { |id| datasource.client.update_reconciliation(id, payload) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def serialize(record)
|
|
28
|
+
a = attrs_of(record)
|
|
29
|
+
{
|
|
30
|
+
'id' => a['id'],
|
|
31
|
+
'object' => a['object'],
|
|
32
|
+
'transaction_id' => a['transaction_id'],
|
|
33
|
+
'payment_id' => a['payment_id'],
|
|
34
|
+
'payment_type' => a['payment_type'],
|
|
35
|
+
'amount' => a['amount'],
|
|
36
|
+
'match_type' => a['match_type'],
|
|
37
|
+
'metadata' => a['metadata'],
|
|
38
|
+
'canceled_at' => a['canceled_at'],
|
|
39
|
+
'created_at' => a['created_at']
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
protected
|
|
44
|
+
|
|
45
|
+
def collection_filters
|
|
46
|
+
{
|
|
47
|
+
'transaction_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
48
|
+
'payment_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
49
|
+
'payment_type' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
50
|
+
'match_type' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def many_to_one_embeds
|
|
55
|
+
[
|
|
56
|
+
{ foreign_key: 'transaction_id', relation_name: 'transaction', collection: 'MambuTransaction' }
|
|
57
|
+
]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def define_schema
|
|
63
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
64
|
+
is_read_only: true, is_sortable: true))
|
|
65
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
66
|
+
# transaction_id is set on create and never mutated afterwards — Numeral
|
|
67
|
+
# rejects PATCH on anything besides metadata.
|
|
68
|
+
add_field('transaction_id', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
69
|
+
# payment_id is polymorphic in Numeral (payment_order / incoming_payment /
|
|
70
|
+
# return / expected_payment / payment_capture, discriminated by
|
|
71
|
+
# payment_type). Forest can't model that natively, so we expose it as
|
|
72
|
+
# a plain string column rather than a typed ManyToOne.
|
|
73
|
+
add_field('payment_id', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
74
|
+
add_field('payment_type', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_PAYMENT_TYPE,
|
|
75
|
+
is_read_only: true, is_sortable: true))
|
|
76
|
+
add_field('amount', ColumnSchema.new(column_type: 'Number', is_read_only: false, is_sortable: false))
|
|
77
|
+
add_field('match_type', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_MATCH_TYPE,
|
|
78
|
+
is_read_only: true, is_sortable: true))
|
|
79
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
80
|
+
add_field('canceled_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
81
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def define_relations
|
|
85
|
+
add_field('transaction', ManyToOneSchema.new(
|
|
86
|
+
foreign_collection: 'MambuTransaction',
|
|
87
|
+
foreign_key: 'transaction_id',
|
|
88
|
+
foreign_key_target: 'id'
|
|
89
|
+
))
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|