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,133 @@
|
|
|
1
|
+
module ForestAdminDatasourceMambuPayments
|
|
2
|
+
module Collections
|
|
3
|
+
class Event < BaseCollection
|
|
4
|
+
PolymorphicManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema
|
|
5
|
+
|
|
6
|
+
# Maps Numeral's `topic` / `related_object_type` enum values to Forest collection
|
|
7
|
+
# names. The polymorphic relation resolver expects the type column to hold the
|
|
8
|
+
# target collection name, so we translate at serialize time.
|
|
9
|
+
TYPE_TO_COLLECTION = {
|
|
10
|
+
'payment_order' => 'MambuPaymentOrder',
|
|
11
|
+
'transaction' => 'MambuTransaction',
|
|
12
|
+
'incoming_payment' => 'MambuIncomingPayment',
|
|
13
|
+
'expected_payment' => 'MambuExpectedPayment',
|
|
14
|
+
'direct_debit_mandate' => 'MambuDirectDebitMandate',
|
|
15
|
+
'balance' => 'MambuBalance',
|
|
16
|
+
'connected_account' => 'MambuConnectedAccount',
|
|
17
|
+
'account_holder' => 'MambuAccountHolder',
|
|
18
|
+
'internal_account' => 'MambuInternalAccount',
|
|
19
|
+
'external_account' => 'MambuExternalAccount'
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
ENUM_STATUS = %w[created delivered pending_retry failed archived].freeze
|
|
23
|
+
|
|
24
|
+
client_resource :event
|
|
25
|
+
|
|
26
|
+
def initialize(datasource)
|
|
27
|
+
super(datasource, 'MambuEvent')
|
|
28
|
+
define_schema
|
|
29
|
+
define_relations
|
|
30
|
+
reconcile_filter_operators!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def serialize(record)
|
|
34
|
+
a = attrs_of(record)
|
|
35
|
+
{
|
|
36
|
+
'id' => a['id'],
|
|
37
|
+
'object' => a['object'],
|
|
38
|
+
'topic' => a['topic'],
|
|
39
|
+
'type' => a['type'],
|
|
40
|
+
'related_object_id' => a['related_object_id'],
|
|
41
|
+
'related_object_type' => TYPE_TO_COLLECTION[a['related_object_type']] || a['related_object_type'],
|
|
42
|
+
'status' => a['status'],
|
|
43
|
+
'status_details' => a['status_details'],
|
|
44
|
+
'webhook_id' => a['webhook_id'],
|
|
45
|
+
'data' => a['data'],
|
|
46
|
+
'created_at' => a['created_at']
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
protected
|
|
51
|
+
|
|
52
|
+
# Numeral's `GET /events` exposes filtering on the polymorphic target id.
|
|
53
|
+
# Used by OneToMany relations declared on PaymentOrder/IncomingPayment/etc
|
|
54
|
+
# to navigate "events of this resource". `related_object_type` filtering
|
|
55
|
+
# is left out because we translate the enum to Forest collection names at
|
|
56
|
+
# serialize time — uniqueness of UUIDs makes the type filter redundant
|
|
57
|
+
# when filtering by id anyway.
|
|
58
|
+
def collection_filters
|
|
59
|
+
{
|
|
60
|
+
'related_object_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# PolymorphicManyToOne is not resolved by the customizer, so we populate
|
|
65
|
+
# `related_object` here when the projection requests it. Ids are grouped by
|
|
66
|
+
# their (translated) related_object_type so each target collection is hit
|
|
67
|
+
# with a single batched fetch_by_ids pass.
|
|
68
|
+
def embed_relations(rows, records, projection)
|
|
69
|
+
return if projection.nil? || !relations_in(projection).include?('related_object')
|
|
70
|
+
|
|
71
|
+
sources = records.map { |r| attrs_of(r) }
|
|
72
|
+
caches = build_related_object_caches(sources)
|
|
73
|
+
|
|
74
|
+
rows.each_with_index do |row, i|
|
|
75
|
+
src = sources[i]
|
|
76
|
+
type = TYPE_TO_COLLECTION[src['related_object_type']]
|
|
77
|
+
id = src['related_object_id']
|
|
78
|
+
next if type.nil? || id.to_s.empty?
|
|
79
|
+
|
|
80
|
+
row['related_object'] = caches.dig(type, id)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def build_related_object_caches(sources)
|
|
87
|
+
ids_by_collection = Hash.new { |hash, key| hash[key] = [] }
|
|
88
|
+
sources.each do |src|
|
|
89
|
+
type = TYPE_TO_COLLECTION[src['related_object_type']]
|
|
90
|
+
id = src['related_object_id']
|
|
91
|
+
next if type.nil? || id.to_s.empty?
|
|
92
|
+
|
|
93
|
+
ids_by_collection[type] << id
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
ids_by_collection.to_h do |collection_name, ids|
|
|
97
|
+
target = datasource.get_collection(collection_name)
|
|
98
|
+
by_id = target.fetch_by_ids(ids).to_h do |raw|
|
|
99
|
+
[attrs_of(raw)['id'], target.serialize(raw)]
|
|
100
|
+
end
|
|
101
|
+
[collection_name, by_id]
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def define_schema
|
|
106
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
107
|
+
is_read_only: true, is_sortable: true))
|
|
108
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
109
|
+
add_field('topic', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
110
|
+
add_field('type', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
111
|
+
add_field('related_object_id', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
112
|
+
is_sortable: false))
|
|
113
|
+
add_field('related_object_type', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
114
|
+
is_sortable: true))
|
|
115
|
+
add_field('status', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_STATUS,
|
|
116
|
+
is_read_only: true, is_sortable: true))
|
|
117
|
+
add_field('status_details', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
118
|
+
add_field('webhook_id', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
119
|
+
add_field('data', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
120
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def define_relations
|
|
124
|
+
add_field('related_object', PolymorphicManyToOneSchema.new(
|
|
125
|
+
foreign_key: 'related_object_id',
|
|
126
|
+
foreign_key_type_field: 'related_object_type',
|
|
127
|
+
foreign_collections: TYPE_TO_COLLECTION.values,
|
|
128
|
+
foreign_key_targets: TYPE_TO_COLLECTION.values.to_h { |n| [n, 'id'] }
|
|
129
|
+
))
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class ExpectedPayment < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
ENUM_DIRECTION = %w[debit credit].freeze
|
|
8
|
+
|
|
9
|
+
client_resource :expected_payment
|
|
10
|
+
|
|
11
|
+
def initialize(datasource)
|
|
12
|
+
super(datasource, 'MambuExpectedPayment')
|
|
13
|
+
define_schema
|
|
14
|
+
define_relations
|
|
15
|
+
reconcile_filter_operators!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create(_caller, data)
|
|
19
|
+
serialize(datasource.client.create_expected_payment(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_expected_payment(id, payload) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete(caller, filter)
|
|
28
|
+
ids_for(caller, filter).each { |id| datasource.client.delete_expected_payment(id) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def serialize(record)
|
|
32
|
+
a = attrs_of(record)
|
|
33
|
+
{
|
|
34
|
+
'id' => a['id'],
|
|
35
|
+
'object' => a['object'],
|
|
36
|
+
'idempotency_key' => a['idempotency_key'],
|
|
37
|
+
'connected_account_id' => a['connected_account_id'],
|
|
38
|
+
'internal_account_id' => a['internal_account_id'],
|
|
39
|
+
'external_account_id' => a['external_account_id'],
|
|
40
|
+
'direction' => a['direction'],
|
|
41
|
+
'amount_from' => a['amount_from'],
|
|
42
|
+
'amount_to' => a['amount_to'],
|
|
43
|
+
'currency' => a['currency'],
|
|
44
|
+
'start_date' => a['start_date'],
|
|
45
|
+
'end_date' => a['end_date'],
|
|
46
|
+
'descriptions' => a['descriptions'],
|
|
47
|
+
'reconciliation_status' => a['reconciliation_status'],
|
|
48
|
+
'reconciled_amount' => a['reconciled_amount'],
|
|
49
|
+
'custom_fields' => a['custom_fields'],
|
|
50
|
+
'metadata' => a['metadata'],
|
|
51
|
+
'created_at' => a['created_at'],
|
|
52
|
+
'updated_at' => a['updated_at'],
|
|
53
|
+
'canceled_at' => a['canceled_at']
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
def collection_filters
|
|
60
|
+
{
|
|
61
|
+
'connected_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
62
|
+
'internal_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
63
|
+
'external_account_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The full account records are exposed through the ManyToOne relations
|
|
68
|
+
# below rather than as embedded snapshot columns, so a single source of
|
|
69
|
+
# truth backs both (mirrors the Transaction collection).
|
|
70
|
+
def many_to_one_embeds
|
|
71
|
+
[
|
|
72
|
+
{ foreign_key: 'connected_account_id', relation_name: 'connected_account',
|
|
73
|
+
collection: 'MambuConnectedAccount' },
|
|
74
|
+
{ foreign_key: 'internal_account_id', relation_name: 'internal_account',
|
|
75
|
+
collection: 'MambuInternalAccount' },
|
|
76
|
+
{ foreign_key: 'external_account_id', relation_name: 'external_account',
|
|
77
|
+
collection: 'MambuExternalAccount' }
|
|
78
|
+
]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def define_schema
|
|
84
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
85
|
+
is_read_only: true, is_sortable: true))
|
|
86
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
87
|
+
add_field('idempotency_key', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
88
|
+
add_field('connected_account_id', ColumnSchema.new(column_type: 'String',
|
|
89
|
+
is_read_only: false, is_sortable: true))
|
|
90
|
+
add_field('internal_account_id', ColumnSchema.new(column_type: 'String',
|
|
91
|
+
is_read_only: false, is_sortable: false))
|
|
92
|
+
add_field('external_account_id', ColumnSchema.new(column_type: 'String',
|
|
93
|
+
is_read_only: false, is_sortable: false))
|
|
94
|
+
add_field('direction', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_DIRECTION,
|
|
95
|
+
is_read_only: false, is_sortable: true))
|
|
96
|
+
add_field('amount_from', ColumnSchema.new(column_type: 'Number', is_read_only: false, is_sortable: false))
|
|
97
|
+
add_field('amount_to', 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('start_date', ColumnSchema.new(column_type: 'Date', is_read_only: false, is_sortable: true))
|
|
100
|
+
add_field('end_date', ColumnSchema.new(column_type: 'Date', is_read_only: false, is_sortable: true))
|
|
101
|
+
add_field('descriptions', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
102
|
+
add_field('reconciliation_status', ColumnSchema.new(column_type: 'String', is_read_only: true,
|
|
103
|
+
is_sortable: true))
|
|
104
|
+
add_field('reconciled_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
105
|
+
add_field('custom_fields', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
106
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
107
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
108
|
+
add_field('updated_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
109
|
+
add_field('canceled_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def define_relations
|
|
113
|
+
add_field('connected_account', ManyToOneSchema.new(
|
|
114
|
+
foreign_collection: 'MambuConnectedAccount',
|
|
115
|
+
foreign_key: 'connected_account_id',
|
|
116
|
+
foreign_key_target: 'id'
|
|
117
|
+
))
|
|
118
|
+
add_field('internal_account', ManyToOneSchema.new(
|
|
119
|
+
foreign_collection: 'MambuInternalAccount',
|
|
120
|
+
foreign_key: 'internal_account_id',
|
|
121
|
+
foreign_key_target: 'id'
|
|
122
|
+
))
|
|
123
|
+
add_field('external_account', ManyToOneSchema.new(
|
|
124
|
+
foreign_collection: 'MambuExternalAccount',
|
|
125
|
+
foreign_key: 'external_account_id',
|
|
126
|
+
foreign_key_target: 'id'
|
|
127
|
+
))
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
# rubocop:enable Metrics/ClassLength
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class ExternalAccount < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
client_resource :external_account
|
|
8
|
+
|
|
9
|
+
def initialize(datasource)
|
|
10
|
+
super(datasource, 'MambuExternalAccount')
|
|
11
|
+
define_schema
|
|
12
|
+
define_relations
|
|
13
|
+
reconcile_filter_operators!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create(_caller, data)
|
|
17
|
+
serialize(datasource.client.create_external_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_external_account(id, payload) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def delete(caller, filter)
|
|
26
|
+
ids_for(caller, filter).each { |id| datasource.client.delete_external_account(id) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def serialize(record)
|
|
30
|
+
a = attrs_of(record)
|
|
31
|
+
{
|
|
32
|
+
'id' => a['id'],
|
|
33
|
+
'object' => a['object'],
|
|
34
|
+
'type' => a['type'],
|
|
35
|
+
'status' => a['status'],
|
|
36
|
+
'status_details' => a['status_details'],
|
|
37
|
+
'name' => a['name'],
|
|
38
|
+
'holder_name' => a['holder_name'],
|
|
39
|
+
'holder_address' => a['holder_address'],
|
|
40
|
+
'account_number' => a['account_number'],
|
|
41
|
+
'account_number_format' => a['account_number_format'],
|
|
42
|
+
'bank_code' => a['bank_code'],
|
|
43
|
+
'bank_name' => a['bank_name'],
|
|
44
|
+
'bank_address' => a['bank_address'],
|
|
45
|
+
'bank_code_format' => a['bank_code_format'],
|
|
46
|
+
'account_holder_id' => a['account_holder_id'],
|
|
47
|
+
'organization_identification' => a['organization_identification'],
|
|
48
|
+
'company_registration_number' => a['company_registration_number'],
|
|
49
|
+
'company_registration_number_type' => a['company_registration_number_type'],
|
|
50
|
+
'metadata' => a['metadata'],
|
|
51
|
+
'custom_fields' => a['custom_fields'],
|
|
52
|
+
'account_verification' => a['account_verification'],
|
|
53
|
+
'idempotency_key' => a['idempotency_key'],
|
|
54
|
+
'created_at' => a['created_at'],
|
|
55
|
+
'disabled_at' => a['disabled_at']
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
protected
|
|
60
|
+
|
|
61
|
+
def collection_filters
|
|
62
|
+
{
|
|
63
|
+
'account_holder_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def many_to_one_embeds
|
|
68
|
+
[
|
|
69
|
+
{ foreign_key: 'account_holder_id', relation_name: 'account_holder',
|
|
70
|
+
collection: 'MambuAccountHolder' }
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def define_schema
|
|
77
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
78
|
+
is_read_only: true, is_sortable: true))
|
|
79
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
80
|
+
add_field('type', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
81
|
+
add_field('status', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
82
|
+
add_field('status_details', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
83
|
+
add_field('name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: true))
|
|
84
|
+
add_field('holder_name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
85
|
+
add_field('holder_address', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
86
|
+
add_field('account_number', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
87
|
+
add_field('account_number_format', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
88
|
+
is_sortable: false))
|
|
89
|
+
add_field('bank_code', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
90
|
+
add_field('bank_name', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
91
|
+
add_field('bank_address', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
92
|
+
add_field('bank_code_format', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
93
|
+
is_sortable: false))
|
|
94
|
+
add_field('account_holder_id', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
95
|
+
is_sortable: true))
|
|
96
|
+
add_field('organization_identification', ColumnSchema.new(column_type: 'Json', is_read_only: false,
|
|
97
|
+
is_sortable: false))
|
|
98
|
+
add_field('company_registration_number', ColumnSchema.new(column_type: 'String', is_read_only: false,
|
|
99
|
+
is_sortable: false))
|
|
100
|
+
add_field('company_registration_number_type',
|
|
101
|
+
ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
102
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
103
|
+
add_field('custom_fields', ColumnSchema.new(column_type: 'Json', is_read_only: false, is_sortable: false))
|
|
104
|
+
add_field('account_verification', ColumnSchema.new(column_type: 'Json', is_read_only: true,
|
|
105
|
+
is_sortable: false))
|
|
106
|
+
add_field('idempotency_key', ColumnSchema.new(column_type: 'String', is_read_only: false, is_sortable: false))
|
|
107
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
108
|
+
add_field('disabled_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def define_relations
|
|
112
|
+
add_field('account_holder', ManyToOneSchema.new(
|
|
113
|
+
foreign_collection: 'MambuAccountHolder',
|
|
114
|
+
foreign_key: 'account_holder_id',
|
|
115
|
+
foreign_key_target: 'id'
|
|
116
|
+
))
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module ForestAdminDatasourceMambuPayments
|
|
2
|
+
module Collections
|
|
3
|
+
class File < BaseCollection
|
|
4
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
5
|
+
|
|
6
|
+
ENUM_DIRECTION = %w[incoming outgoing].freeze
|
|
7
|
+
ENUM_STATUS = %w[created approved canceled sent rejected processed received].freeze
|
|
8
|
+
|
|
9
|
+
client_resource :file
|
|
10
|
+
|
|
11
|
+
def initialize(datasource)
|
|
12
|
+
super(datasource, 'MambuFile')
|
|
13
|
+
define_schema
|
|
14
|
+
define_relations
|
|
15
|
+
reconcile_filter_operators!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def serialize(record)
|
|
19
|
+
a = attrs_of(record)
|
|
20
|
+
{
|
|
21
|
+
'id' => a['id'],
|
|
22
|
+
'object' => a['object'],
|
|
23
|
+
'connected_account_id' => a['connected_account_id'],
|
|
24
|
+
'connected_account_ids' => a['connected_account_ids'],
|
|
25
|
+
'direction' => a['direction'],
|
|
26
|
+
'category' => a['category'],
|
|
27
|
+
'format' => a['format'],
|
|
28
|
+
'filename' => a['filename'],
|
|
29
|
+
'size' => a['size'],
|
|
30
|
+
'summary' => a['summary'],
|
|
31
|
+
'status' => a['status'],
|
|
32
|
+
'status_details' => a['status_details'],
|
|
33
|
+
'bank_data' => a['bank_data'],
|
|
34
|
+
'created_at' => a['created_at']
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
protected
|
|
39
|
+
|
|
40
|
+
def collection_filters
|
|
41
|
+
{
|
|
42
|
+
'connected_account_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def many_to_one_embeds
|
|
47
|
+
[
|
|
48
|
+
{ foreign_key: 'connected_account_id', relation_name: 'connected_account',
|
|
49
|
+
collection: 'MambuConnectedAccount' }
|
|
50
|
+
]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def define_schema
|
|
56
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
57
|
+
is_read_only: true, is_sortable: true))
|
|
58
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
59
|
+
add_field('connected_account_id', ColumnSchema.new(column_type: 'String',
|
|
60
|
+
is_read_only: true, is_sortable: true))
|
|
61
|
+
# The API also returns connected_account_ids (an array) for files that
|
|
62
|
+
# aggregate operations across multiple accounts; surfaced as Json since
|
|
63
|
+
# Forest can't model an array of foreign keys natively.
|
|
64
|
+
add_field('connected_account_ids', ColumnSchema.new(column_type: 'Json', is_read_only: true,
|
|
65
|
+
is_sortable: false))
|
|
66
|
+
add_field('direction', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_DIRECTION,
|
|
67
|
+
is_read_only: true, is_sortable: true))
|
|
68
|
+
add_field('category', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
69
|
+
add_field('format', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
70
|
+
add_field('filename', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
71
|
+
add_field('size', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: true))
|
|
72
|
+
add_field('summary', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
73
|
+
add_field('status', ColumnSchema.new(column_type: 'Enum', enum_values: ENUM_STATUS,
|
|
74
|
+
is_read_only: true, is_sortable: true))
|
|
75
|
+
add_field('status_details', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
76
|
+
add_field('bank_data', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
77
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def define_relations
|
|
81
|
+
add_field('connected_account', ManyToOneSchema.new(
|
|
82
|
+
foreign_collection: 'MambuConnectedAccount',
|
|
83
|
+
foreign_key: 'connected_account_id',
|
|
84
|
+
foreign_key_target: 'id'
|
|
85
|
+
))
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength
|
|
2
|
+
module ForestAdminDatasourceMambuPayments
|
|
3
|
+
module Collections
|
|
4
|
+
class IncomingPayment < BaseCollection
|
|
5
|
+
ManyToOneSchema = ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema
|
|
6
|
+
|
|
7
|
+
client_resource :incoming_payment
|
|
8
|
+
|
|
9
|
+
def initialize(datasource)
|
|
10
|
+
super(datasource, 'MambuIncomingPayment')
|
|
11
|
+
define_schema
|
|
12
|
+
define_relations
|
|
13
|
+
reconcile_filter_operators!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def serialize(record)
|
|
17
|
+
a = attrs_of(record)
|
|
18
|
+
{
|
|
19
|
+
'id' => a['id'],
|
|
20
|
+
'object' => a['object'],
|
|
21
|
+
'connected_account_id' => a['connected_account_id'],
|
|
22
|
+
'type' => a['type'],
|
|
23
|
+
'status' => a['status'],
|
|
24
|
+
'amount' => a['amount'],
|
|
25
|
+
'currency' => a['currency'],
|
|
26
|
+
'end_to_end_id' => a['end_to_end_id'],
|
|
27
|
+
'uetr' => a['uetr'],
|
|
28
|
+
'reference' => a['reference'],
|
|
29
|
+
'structured_reference' => a['structured_reference'],
|
|
30
|
+
'value_date' => a['value_date'],
|
|
31
|
+
'booking_date' => a['booking_date'],
|
|
32
|
+
'originating_account' => a['originating_account'],
|
|
33
|
+
'receiving_account' => a['receiving_account'],
|
|
34
|
+
'internal_account_id' => a['internal_account_id'],
|
|
35
|
+
'external_account_id' => a['external_account_id'],
|
|
36
|
+
'reconciliation_status' => a['reconciliation_status'],
|
|
37
|
+
'reconciled_amount' => a['reconciled_amount'],
|
|
38
|
+
'return_information' => a['return_information'],
|
|
39
|
+
'custom_fields' => a['custom_fields'],
|
|
40
|
+
'metadata' => a['metadata'],
|
|
41
|
+
'created_at' => a['created_at']
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def collection_filters
|
|
48
|
+
{
|
|
49
|
+
'connected_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
50
|
+
'internal_account_id' => { ops: [Operators::EQUAL, Operators::IN] },
|
|
51
|
+
'external_account_id' => { ops: [Operators::EQUAL, Operators::IN] }
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def many_to_one_embeds
|
|
56
|
+
[
|
|
57
|
+
{ foreign_key: 'connected_account_id', relation_name: 'connected_account',
|
|
58
|
+
collection: 'MambuConnectedAccount' },
|
|
59
|
+
{ foreign_key: 'internal_account_id', relation_name: 'internal_account',
|
|
60
|
+
collection: 'MambuInternalAccount' },
|
|
61
|
+
{ foreign_key: 'external_account_id', relation_name: 'external_account',
|
|
62
|
+
collection: 'MambuExternalAccount' }
|
|
63
|
+
]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def define_schema
|
|
69
|
+
add_field('id', ColumnSchema.new(column_type: 'String', is_primary_key: true,
|
|
70
|
+
is_read_only: true, is_sortable: true))
|
|
71
|
+
add_field('object', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
72
|
+
add_field('connected_account_id', ColumnSchema.new(column_type: 'String',
|
|
73
|
+
is_read_only: true, is_sortable: true))
|
|
74
|
+
add_field('type', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
75
|
+
add_field('status', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: true))
|
|
76
|
+
add_field('amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
77
|
+
add_field('currency', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
78
|
+
add_field('end_to_end_id', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
79
|
+
add_field('uetr', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
80
|
+
add_field('reference', ColumnSchema.new(column_type: 'String', is_read_only: true, is_sortable: false))
|
|
81
|
+
add_field('structured_reference', ColumnSchema.new(column_type: 'String',
|
|
82
|
+
is_read_only: true, is_sortable: false))
|
|
83
|
+
add_field('value_date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
84
|
+
add_field('booking_date', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
85
|
+
add_field('originating_account', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
86
|
+
add_field('receiving_account', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
87
|
+
add_field('internal_account_id', ColumnSchema.new(column_type: 'String',
|
|
88
|
+
is_read_only: true, is_sortable: false))
|
|
89
|
+
add_field('external_account_id', ColumnSchema.new(column_type: 'String',
|
|
90
|
+
is_read_only: true, is_sortable: false))
|
|
91
|
+
add_field('reconciliation_status', ColumnSchema.new(column_type: 'String',
|
|
92
|
+
is_read_only: true, is_sortable: true))
|
|
93
|
+
add_field('reconciled_amount', ColumnSchema.new(column_type: 'Number', is_read_only: true, is_sortable: false))
|
|
94
|
+
add_field('return_information', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
95
|
+
add_field('custom_fields', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
96
|
+
add_field('metadata', ColumnSchema.new(column_type: 'Json', is_read_only: true, is_sortable: false))
|
|
97
|
+
add_field('created_at', ColumnSchema.new(column_type: 'Date', is_read_only: true, is_sortable: true))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def define_relations
|
|
101
|
+
add_field('connected_account', ManyToOneSchema.new(
|
|
102
|
+
foreign_collection: 'MambuConnectedAccount',
|
|
103
|
+
foreign_key: 'connected_account_id',
|
|
104
|
+
foreign_key_target: 'id'
|
|
105
|
+
))
|
|
106
|
+
add_field('internal_account', ManyToOneSchema.new(
|
|
107
|
+
foreign_collection: 'MambuInternalAccount',
|
|
108
|
+
foreign_key: 'internal_account_id',
|
|
109
|
+
foreign_key_target: 'id'
|
|
110
|
+
))
|
|
111
|
+
add_field('external_account', ManyToOneSchema.new(
|
|
112
|
+
foreign_collection: 'MambuExternalAccount',
|
|
113
|
+
foreign_key: 'external_account_id',
|
|
114
|
+
foreign_key_target: 'id'
|
|
115
|
+
))
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength
|