fintoc 1.0.0 → 1.2.0

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: 2b6fd84b01a0debcf2e3641566db792081bc9d101a4aa7c16c5de4833e573fca
4
- data.tar.gz: 72ae1022ebe59fb82ce5ce68ca4327d70975fbe87f64b4b20df6d0d30705f7ec
3
+ metadata.gz: a1a0932a63c0c93038089b3054adbe8c105e82248627ce22105fa7e785548ecf
4
+ data.tar.gz: 03e8f9737a40f23f03dec7d293b0741e6b95477ef3330181f7d0d0396fa98b03
5
5
  SHA512:
6
- metadata.gz: d5d6354afddadc96ddd7b4795e6d7b6d4679fb9838378f0b6f3a130442a35505e518394aabf3ebc543d6b9dad7071f5141853e747a7832e2bc8920a57d719cd6
7
- data.tar.gz: 9d98cb9b5f113793b62458d55e6f425ff7dc3f8a811a7f664fdf09630e7bcbcfa3234a95ebb903648ba3053981e4acfd9bfb76471ae49c44c0d670bb368518ce
6
+ metadata.gz: 67767ca7af9b52848bb8224134b352c1e83999cb3e4650ee248a0b241d31d476521c2422fbb821130463968d18b4e828bf55aedcf9269702483f478bd4665cc9
7
+ data.tar.gz: 934617f315dfb320eb14fe2974272e17b9b17b87bf942c1b6fa6fb23192bf56cf4bd113724e89390282b1966d53d3f7f7392a11c68644ccb372e36d13e00bb2c
@@ -44,4 +44,3 @@ Ej.:
44
44
 
45
45
  ¿Es seguro hacer rollback?
46
46
  ¿Cuáles son los pasos para hacer rollback?
47
- ****
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.0 - 2026-04-08
4
+
5
+ ### 🚀 New Features
6
+
7
+ - **Account Statements**: Added `account_statements` resource under v2 accounts for retrieving account statements
8
+ - **Account Number Deletion**: Added `delete` method for account numbers in the v2 API
9
+ - **Movements**: Added `movements` resource under v2 accounts
10
+
11
+ ## 1.1.0 - 2025-09-15
12
+
13
+ ### 🚀 New Features
14
+
15
+ - **Idempotency Key Support**: Added comprehensive idempotency key support across all V2 API operations to help prevent duplicate operations during network issues or retries
16
+ - **Accounts**: `create` and `update` methods now accept the `idempotency_key` parameter
17
+ - **Account Numbers**: `create` and `update` methods support idempotency keys
18
+ - **Transfers**: `create` and `return` operations support idempotency keys
19
+ - **Account Verifications**: `create` method supports idempotency keys
20
+ - **Simulation**: `receive_transfer` method supports idempotency keys
21
+ - **Resource-level methods**: Instance methods like `account.update`, `transfer.return_transfer`, and `account.simulate_receive_transfer` all support idempotency keys
22
+
3
23
  ## 1.0.0 - 2025-09-05
4
24
 
5
25
  ### 🚀 New Features
@@ -12,7 +32,7 @@
12
32
 
13
33
  - **V2 Client - Transfers API Implementation**: Partial implementation of Transfers API endpoints in `Fintoc::V2::Client`
14
34
  - **Entities**: List and retrieve business entities
15
- - **Transfer Accounts**: Create, read, update, and list transfer accounts
35
+ - **Accounts**: Create, read, update, and list accounts
16
36
  - **Account Numbers**: Manage account numbers/CLABEs
17
37
  - **Transfers**: Create, retrieve, list, and return transfers
18
38
  - **Simulation**: Simulate receiving transfers for testing
@@ -42,4 +62,4 @@
42
62
 
43
63
  Initial version
44
64
 
45
- * Up to date with the [2020-11-17](https://docs.fintoc.com/docs/api-changelog#2020-11-17) API version
65
+ - Up to date with the [2020-11-17](https://docs.fintoc.com/docs/api-changelog#2020-11-17) API version
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fintoc (1.0.0)
4
+ fintoc (1.2.0)
5
5
  http
6
6
  money-rails
7
7
  tabulate
data/README.md CHANGED
@@ -28,11 +28,19 @@ Do yourself a favor: go grab some ice cubes by installing this refreshing librar
28
28
  - [Get movements](#get-movements)
29
29
  - [Transfers API Examples](#transfers-api-examples)
30
30
  - [Entities](#entities)
31
- - [Transfer Accounts](#transfer-accounts)
31
+ - [Accounts](#accounts)
32
32
  - [Account Numbers](#account-numbers)
33
33
  - [Transfers](#transfers)
34
34
  - [Simulate](#simulate)
35
35
  - [Account Verifications](#account-verifications)
36
+ - [Idempotency Keys](#idempotency-keys)
37
+ - [Idempotency Examples](#idempotency-examples)
38
+ - [Account Methods with Idempotency Key](#account-methods-with-idempotency-key)
39
+ - [Account Number Methods with Idempotency Key](#account-number-methods-with-idempotency-key)
40
+ - [Transfer Methods with Idempotency Key](#transfer-methods-with-idempotency-key)
41
+ - [Simulation with Idempotency Key](#simulation-with-idempotency-key)
42
+ - [Account Verification with Idempotency Key](#account-verification-with-idempotency-key)
43
+ - [About idempotency keys](#about-idempotency-keys)
36
44
  - [Development](#development)
37
45
  - [Dependencies](#dependencies)
38
46
  - [Setup](#setup)
@@ -107,7 +115,7 @@ client = Fintoc::Client.new('api_key', jws_private_key: 'jws_private_key')
107
115
  entities = client.v2.entities.list
108
116
  entity = client.v2.entities.get('entity_id')
109
117
 
110
- # Transfer Accounts
118
+ # Accounts
111
119
  accounts = client.v2.accounts.list
112
120
  account = client.v2.accounts.get('account_id')
113
121
  account = client.v2.accounts.create(entity_id: 'entity_id', description: 'My Account')
@@ -265,14 +273,14 @@ You can also list entities with pagination:
265
273
  entities = client.v2.entities.list(limit: 10, starting_after: 'entity_id')
266
274
  ```
267
275
 
268
- #### Transfer Accounts
276
+ #### Accounts
269
277
 
270
278
  ```ruby
271
279
  require 'fintoc'
272
280
 
273
281
  client = Fintoc::Client.new('api_key', jws_private_key: 'jws_private_key')
274
282
 
275
- # Create a transfer account
283
+ # Create an account
276
284
  account = client.v2.accounts.create(
277
285
  entity_id: 'entity_id',
278
286
  description: 'My Business Account'
@@ -378,6 +386,116 @@ account_verification = client.v2.account_verifications.get('account_verification
378
386
  account_verifications = client.v2.account_verifications.list
379
387
  ```
380
388
 
389
+ ## Idempotency Keys
390
+
391
+ The Fintoc API supports [idempotency](https://docs.fintoc.com/reference/idempotent-requests) for safely retrying requests without accidentally performing the same operation twice. This is particularly useful when creating transfers, account numbers, accounts, or other resources where you want to avoid duplicates due to network issues.
392
+
393
+ To use idempotency keys, provide an `idempotency_key` parameter when making POST/PATCH requests:
394
+
395
+ ### Idempotency Examples
396
+
397
+ #### Account Methods with Idempotency Key
398
+
399
+ Create and update methods support the use of idempotency keys to prevent duplication:
400
+
401
+ ```ruby
402
+ require 'fintoc'
403
+ require 'securerandom'
404
+
405
+ client = Fintoc::Client.new('api_key', jws_private_key: 'jws_private_key')
406
+
407
+ idempotency_key = SecureRandom.uuid
408
+ account = client.v2.accounts.create(
409
+ entity_id: 'entity_id', description: 'My Business Account', idempotency_key:
410
+ )
411
+
412
+ idempotency_key = SecureRandom.uuid
413
+ updated_account = client.v2.accounts.update(
414
+ 'account_id', description: 'Updated Description', idempotency_key:
415
+ )
416
+ ```
417
+
418
+ Simulation of transfers can also be done with idempotency key:
419
+
420
+ ```ruby
421
+ idempotency_key = SecureRandom.uuid
422
+ account.simulate_receive_transfer(amount: 1000, idempotency_key:)
423
+ ```
424
+
425
+ #### Account Number Methods with Idempotency Key
426
+
427
+ Create and update methods support the use of idempotency keys as well:
428
+
429
+ ```ruby
430
+ idempotency_key = SecureRandom.uuid
431
+ account_number = client.v2.account_numbers.create(
432
+ account_id: 'account_id', description: 'Main account number', idempotency_key:
433
+ )
434
+
435
+ idempotency_key = SecureRandom.uuid
436
+ updated_account_number = client.v2.account_numbers.update(
437
+ 'account_number_id', description: 'Updated description', idempotency_key:
438
+ )
439
+ ```
440
+
441
+ Simulation of transfers can also be done with idempotency key:
442
+
443
+ ```ruby
444
+ account_number.simulate_receive_transfer(amount: 1000, currency: 'MXN', idempotency_key:)
445
+ ```
446
+
447
+ #### Transfer Methods with Idempotency Key
448
+
449
+ Creating and returning transfers support the use of idempotency keys:
450
+
451
+ ```ruby
452
+ idempotency_key = SecureRandom.uuid
453
+ transfer = client.v2.transfers.create(
454
+ amount: 10000, currency: 'CLP', account_id: 'account_id', counterparty: { ... }, idempotency_key:
455
+ )
456
+
457
+ idempotency_key = SecureRandom.uuid
458
+ returned_transfer = client.v2.transfers.return('transfer_id', idempotency_key:)
459
+ ```
460
+
461
+ Returning a transfer as an instance method also supports the use of idempotency key:
462
+
463
+ ```ruby
464
+ idempotency_key = SecureRandom.uuid
465
+ transfer.return_transfer(idempotency_key:)
466
+ ```
467
+
468
+ #### Simulation with Idempotency Key
469
+
470
+ For simulating transfers, the use of idempotency keys is also supported:
471
+
472
+ ```ruby
473
+ idempotency_key = SecureRandom.uuid
474
+ simulated_transfer = client.v2.simulate.receive_transfer(
475
+ account_number_id: 'account_number_id', amount: 5000, currency: 'CLP', idempotency_key:
476
+ )
477
+ ```
478
+
479
+ #### Account Verification with Idempotency Key
480
+
481
+ ```ruby
482
+ idempotency_key = SecureRandom.uuid
483
+ account_verification = client.v2.account_verifications.create(
484
+ account_number: 'account_number', idempotency_key:
485
+ )
486
+ ```
487
+
488
+ ### About idempotency keys
489
+
490
+ - Idempotency keys can be up to 255 characters long
491
+ - Use consistent unique identifiers for the same logical operation (e.g. order IDs, transaction references). If you set them randomly, we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.
492
+ - The same idempotency key will return the same result, including errors
493
+ - Keys are automatically removed after 24 hours
494
+ - Only POST and PATCH requests currently support idempotency keys
495
+ - If parameters differ with the same key, an error will be raised
496
+
497
+ For more information, see the [Fintoc API documentation on idempotent requests](https://docs.fintoc.com/reference/idempotent-requests).
498
+
381
499
  ## Development
382
500
 
383
501
  ### Dependencies
@@ -23,25 +23,25 @@ module Fintoc
23
23
  end
24
24
 
25
25
  def get(version: :v1)
26
- request('get', version: version)
26
+ request('get', version:)
27
27
  end
28
28
 
29
29
  def delete(version: :v1)
30
- request('delete', version: version)
30
+ request('delete', version:)
31
31
  end
32
32
 
33
- def post(version: :v1, use_jws: false)
34
- request('post', version: version, use_jws: use_jws)
33
+ def post(version: :v1, use_jws: false, idempotency_key: nil)
34
+ request('post', version:, use_jws:, idempotency_key:)
35
35
  end
36
36
 
37
- def patch(version: :v1, use_jws: false)
38
- request('patch', version: version, use_jws: use_jws)
37
+ def patch(version: :v1, use_jws: false, idempotency_key: nil)
38
+ request('patch', version:, use_jws:, idempotency_key:)
39
39
  end
40
40
 
41
- def request(method, version: :v1, use_jws: false)
41
+ def request(method, version: :v1, use_jws: false, idempotency_key: nil)
42
42
  proc do |resource, **kwargs|
43
43
  parameters = params(method, **kwargs)
44
- response = make_request(method, resource, parameters, version: version, use_jws: use_jws)
44
+ response = make_request(method, resource, parameters, version:, use_jws:, idempotency_key:)
45
45
  content = JSON.parse(response.body, symbolize_names: true)
46
46
 
47
47
  if response.status.client_error? || response.status.server_error?
@@ -91,7 +91,13 @@ module Fintoc
91
91
  use_jws && @jws && %w[post patch put].include?(method.downcase)
92
92
  end
93
93
 
94
- def make_request(method, resource, parameters, version: :v1, use_jws: false)
94
+ def should_use_idempotency_key?(method, idempotency_key)
95
+ idempotency_key && %w[post patch put].include?(method.downcase)
96
+ end
97
+
98
+ def make_request(
99
+ method, resource, parameters, version: :v1, use_jws: false, idempotency_key: nil
100
+ )
95
101
  # this is to handle url returned in the link headers
96
102
  # I'm sure there is a better and more clever way to solve this
97
103
  if resource.start_with? 'https'
@@ -99,15 +105,20 @@ module Fintoc
99
105
  end
100
106
 
101
107
  url = build_url(resource, version:)
108
+ request_client = client
102
109
 
103
110
  if should_use_jws?(method, use_jws)
104
111
  request_body = parameters[:json]&.to_json || ''
105
112
  jws_signature = @jws.generate_signature(request_body)
106
113
 
107
- return client.headers('Fintoc-JWS-Signature' => jws_signature).send(method, url, parameters)
114
+ request_client = request_client.headers('Fintoc-JWS-Signature' => jws_signature)
115
+ end
116
+
117
+ if should_use_idempotency_key?(method, idempotency_key)
118
+ request_client = request_client.headers('Idempotency-Key' => idempotency_key)
108
119
  end
109
120
 
110
- client.send(method, url, parameters)
121
+ request_client.send(method, url, parameters)
111
122
  end
112
123
 
113
124
  def params(method, **kwargs)
@@ -8,8 +8,10 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
- def create(account_id:, description: nil, metadata: nil, **params)
12
- data = _create_account_number(account_id:, description:, metadata:, **params)
11
+ def create(account_id:, description: nil, metadata: nil, idempotency_key: nil, **params)
12
+ data = _create_account_number(
13
+ account_id:, description:, metadata:, idempotency_key:, **params
14
+ )
13
15
  build_account_number(data)
14
16
  end
15
17
 
@@ -22,20 +24,26 @@ module Fintoc
22
24
  _list_account_numbers(**params).map { |data| build_account_number(data) }
23
25
  end
24
26
 
25
- def update(account_number_id, **params)
26
- data = _update_account_number(account_number_id, **params)
27
+ def update(account_number_id, idempotency_key: nil, **params)
28
+ data = _update_account_number(account_number_id, idempotency_key:, **params)
27
29
  build_account_number(data)
28
30
  end
29
31
 
32
+ def delete(account_number_id)
33
+ _delete_account_number(account_number_id)
34
+ end
35
+
30
36
  private
31
37
 
32
- def _create_account_number(account_id:, description: nil, metadata: nil, **params)
38
+ def _create_account_number(
39
+ account_id:, description: nil, metadata: nil, idempotency_key: nil, **params
40
+ )
33
41
  request_params = { account_id: }
34
42
  request_params[:description] = description if description
35
43
  request_params[:metadata] = metadata if metadata
36
44
  request_params.merge!(params)
37
45
 
38
- @client.post(version: :v2).call('account_numbers', **request_params)
46
+ @client.post(version: :v2, idempotency_key:).call('account_numbers', **request_params)
39
47
  end
40
48
 
41
49
  def _get_account_number(account_number_id)
@@ -46,8 +54,13 @@ module Fintoc
46
54
  @client.get(version: :v2).call('account_numbers', **params)
47
55
  end
48
56
 
49
- def _update_account_number(account_number_id, **params)
50
- @client.patch(version: :v2).call("account_numbers/#{account_number_id}", **params)
57
+ def _update_account_number(account_number_id, idempotency_key: nil, **params)
58
+ @client.patch(version: :v2, idempotency_key:)
59
+ .call("account_numbers/#{account_number_id}", **params)
60
+ end
61
+
62
+ def _delete_account_number(account_number_id)
63
+ @client.delete(version: :v2).call("account_numbers/#{account_number_id}")
51
64
  end
52
65
 
53
66
  def build_account_number(data)
@@ -0,0 +1,28 @@
1
+ require 'fintoc/v2/resources/account_statement'
2
+
3
+ module Fintoc
4
+ module V2
5
+ module Managers
6
+ class AccountStatementsManager
7
+ def initialize(client, account_id)
8
+ @client = client
9
+ @account_id = account_id
10
+ end
11
+
12
+ def list(**params)
13
+ _list_account_statements(**params).map { |data| build_account_statement(data) }
14
+ end
15
+
16
+ private
17
+
18
+ def _list_account_statements(**params)
19
+ @client.get(version: :v2).call("accounts/#{@account_id}/account_statements", **params)
20
+ end
21
+
22
+ def build_account_statement(data)
23
+ Fintoc::V2::AccountStatement.new(**data)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -8,8 +8,8 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
- def create(account_number:)
12
- data = _create_account_verification(account_number:)
11
+ def create(account_number:, idempotency_key: nil)
12
+ data = _create_account_verification(account_number:, idempotency_key:)
13
13
  build_account_verification(data)
14
14
  end
15
15
 
@@ -24,8 +24,9 @@ module Fintoc
24
24
 
25
25
  private
26
26
 
27
- def _create_account_verification(account_number:)
28
- @client.post(version: :v2, use_jws: true).call('account_verifications', account_number:)
27
+ def _create_account_verification(account_number:, idempotency_key: nil)
28
+ @client.post(version: :v2, use_jws: true, idempotency_key:)
29
+ .call('account_verifications', account_number:)
29
30
  end
30
31
 
31
32
  def _get_account_verification(account_verification_id)
@@ -8,8 +8,8 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
- def create(entity_id:, description:, **params)
12
- data = _create_account(entity_id:, description:, **params)
11
+ def create(entity_id:, description:, idempotency_key: nil, **params)
12
+ data = _create_account(entity_id:, description:, idempotency_key:, **params)
13
13
  build_account(data)
14
14
  end
15
15
 
@@ -22,15 +22,16 @@ module Fintoc
22
22
  _list_accounts(**params).map { |data| build_account(data) }
23
23
  end
24
24
 
25
- def update(account_id, **params)
26
- data = _update_account(account_id, **params)
25
+ def update(account_id, idempotency_key: nil, **params)
26
+ data = _update_account(account_id, idempotency_key:, **params)
27
27
  build_account(data)
28
28
  end
29
29
 
30
30
  private
31
31
 
32
- def _create_account(entity_id:, description:, **params)
33
- @client.post(version: :v2).call('accounts', entity_id:, description:, **params)
32
+ def _create_account(entity_id:, description:, idempotency_key: nil, **params)
33
+ @client.post(version: :v2, idempotency_key:)
34
+ .call('accounts', entity_id:, description:, **params)
34
35
  end
35
36
 
36
37
  def _get_account(account_id)
@@ -41,8 +42,8 @@ module Fintoc
41
42
  @client.get(version: :v2).call('accounts', **params)
42
43
  end
43
44
 
44
- def _update_account(account_id, **params)
45
- @client.patch(version: :v2).call("accounts/#{account_id}", **params)
45
+ def _update_account(account_id, idempotency_key: nil, **params)
46
+ @client.patch(version: :v2, idempotency_key:).call("accounts/#{account_id}", **params)
46
47
  end
47
48
 
48
49
  def build_account(data)
@@ -0,0 +1,38 @@
1
+ require 'fintoc/v2/resources/movement'
2
+
3
+ module Fintoc
4
+ module V2
5
+ module Managers
6
+ class MovementsManager
7
+ def initialize(client, account_id)
8
+ @client = client
9
+ @account_id = account_id
10
+ end
11
+
12
+ def list(**params)
13
+ _list_movements(**params).map { |data| build_movement(data) }
14
+ end
15
+
16
+ def get(movement_id, **params)
17
+ data = _get_movement(movement_id, **params)
18
+ build_movement(data)
19
+ end
20
+
21
+ private
22
+
23
+ def _list_movements(**params)
24
+ @client.get(version: :v2).call("accounts/#{@account_id}/movements", **params)
25
+ end
26
+
27
+ def _get_movement(movement_id, **params)
28
+ path = "accounts/#{@account_id}/movements/#{movement_id}"
29
+ @client.get(version: :v2).call(path, **params)
30
+ end
31
+
32
+ def build_movement(data)
33
+ Fintoc::V2::Movement.new(**data)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -8,16 +8,18 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
- def receive_transfer(account_number_id:, amount:, currency:)
12
- data = _simulate_receive_transfer(account_number_id:, amount:, currency:)
11
+ def receive_transfer(account_number_id:, amount:, currency:, idempotency_key: nil)
12
+ data = _simulate_receive_transfer(
13
+ account_number_id:, amount:, currency:, idempotency_key:
14
+ )
13
15
  build_transfer(data)
14
16
  end
15
17
 
16
18
  private
17
19
 
18
- def _simulate_receive_transfer(account_number_id:, amount:, currency:)
20
+ def _simulate_receive_transfer(account_number_id:, amount:, currency:, idempotency_key: nil)
19
21
  @client
20
- .post(version: :v2)
22
+ .post(version: :v2, idempotency_key:)
21
23
  .call('simulate/receive_transfer', account_number_id:, amount:, currency:)
22
24
  end
23
25
 
@@ -8,8 +8,10 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
- def create(amount:, currency:, account_id:, counterparty:, **params)
12
- data = _create_transfer(amount:, currency:, account_id:, counterparty:, **params)
11
+ def create(amount:, currency:, account_id:, counterparty:, idempotency_key: nil, **params)
12
+ data = _create_transfer(
13
+ amount:, currency:, account_id:, counterparty:, idempotency_key:, **params
14
+ )
13
15
  build_transfer(data)
14
16
  end
15
17
 
@@ -22,16 +24,18 @@ module Fintoc
22
24
  _list_transfers(**params).map { |data| build_transfer(data) }
23
25
  end
24
26
 
25
- def return(transfer_id)
26
- data = _return_transfer(transfer_id)
27
+ def return(transfer_id, idempotency_key: nil)
28
+ data = _return_transfer(transfer_id, idempotency_key:)
27
29
  build_transfer(data)
28
30
  end
29
31
 
30
32
  private
31
33
 
32
- def _create_transfer(amount:, currency:, account_id:, counterparty:, **params)
34
+ def _create_transfer(
35
+ amount:, currency:, account_id:, counterparty:, idempotency_key: nil, **params
36
+ )
33
37
  @client
34
- .post(version: :v2, use_jws: true)
38
+ .post(version: :v2, use_jws: true, idempotency_key:)
35
39
  .call('transfers', amount:, currency:, account_id:, counterparty:, **params)
36
40
  end
37
41
 
@@ -43,8 +47,9 @@ module Fintoc
43
47
  @client.get(version: :v2).call('transfers', **params)
44
48
  end
45
49
 
46
- def _return_transfer(transfer_id)
47
- @client.post(version: :v2, use_jws: true).call('transfers/return', transfer_id:)
50
+ def _return_transfer(transfer_id, idempotency_key: nil)
51
+ @client.post(version: :v2, use_jws: true, idempotency_key:)
52
+ .call('transfers/return', transfer_id:)
48
53
  end
49
54
 
50
55
  def build_transfer(data)
@@ -1,4 +1,6 @@
1
1
  require 'money'
2
+ require 'fintoc/v2/managers/account_statements_manager'
3
+ require 'fintoc/v2/managers/movements_manager'
2
4
 
3
5
  module Fintoc
4
6
  module V2
@@ -44,11 +46,11 @@ module Fintoc
44
46
  refresh_from_account(fresh_account)
45
47
  end
46
48
 
47
- def update(description: nil)
49
+ def update(description: nil, idempotency_key: nil)
48
50
  params = {}
49
51
  params[:description] = description if description
50
52
 
51
- updated_account = @client.accounts.update(@id, **params)
53
+ updated_account = @client.accounts.update(@id, idempotency_key:, **params)
52
54
  refresh_from_account(updated_account)
53
55
  end
54
56
 
@@ -68,7 +70,7 @@ module Fintoc
68
70
  @mode == 'test'
69
71
  end
70
72
 
71
- def simulate_receive_transfer(amount:)
73
+ def simulate_receive_transfer(amount:, idempotency_key: nil)
72
74
  unless test_mode?
73
75
  raise Fintoc::Errors::InvalidRequestError, 'Simulation is only available in test mode'
74
76
  end
@@ -76,10 +78,19 @@ module Fintoc
76
78
  @client.simulate.receive_transfer(
77
79
  account_number_id: @root_account_number_id,
78
80
  amount:,
79
- currency: @currency
81
+ currency: @currency,
82
+ idempotency_key:
80
83
  )
81
84
  end
82
85
 
86
+ def account_statements
87
+ @account_statements ||= Managers::AccountStatementsManager.new(@client, @id)
88
+ end
89
+
90
+ def movements
91
+ @movements ||= Managers::MovementsManager.new(@client, @id)
92
+ end
93
+
83
94
  private
84
95
 
85
96
  def refresh_from_account(account)
@@ -2,7 +2,8 @@ module Fintoc
2
2
  module V2
3
3
  class AccountNumber
4
4
  attr_reader :id, :object, :description, :number, :created_at, :updated_at,
5
- :mode, :status, :is_root, :account_id, :metadata
5
+ :mode, :status, :is_root, :account_id, :metadata,
6
+ :last_transfer_at, :deleted_at
6
7
 
7
8
  def initialize(
8
9
  id:,
@@ -16,6 +17,8 @@ module Fintoc
16
17
  is_root:,
17
18
  account_id:,
18
19
  metadata:,
20
+ last_transfer_at: nil,
21
+ deleted_at: nil,
19
22
  client: nil,
20
23
  **
21
24
  )
@@ -30,6 +33,8 @@ module Fintoc
30
33
  @is_root = is_root
31
34
  @account_id = account_id
32
35
  @metadata = metadata
36
+ @last_transfer_at = last_transfer_at
37
+ @deleted_at = deleted_at
33
38
  @client = client
34
39
  end
35
40
 
@@ -42,13 +47,13 @@ module Fintoc
42
47
  refresh_from_account_number(fresh_account_number)
43
48
  end
44
49
 
45
- def update(description: nil, status: nil, metadata: nil)
50
+ def update(description: nil, status: nil, metadata: nil, idempotency_key: nil)
46
51
  params = {}
47
52
  params[:description] = description if description
48
53
  params[:status] = status if status
49
54
  params[:metadata] = metadata if metadata
50
55
 
51
- updated_account_number = @client.account_numbers.update(@id, **params)
56
+ updated_account_number = @client.account_numbers.update(@id, idempotency_key:, **params)
52
57
  refresh_from_account_number(updated_account_number)
53
58
  end
54
59
 
@@ -68,7 +73,7 @@ module Fintoc
68
73
  @mode == 'test'
69
74
  end
70
75
 
71
- def simulate_receive_transfer(amount:, currency: 'MXN')
76
+ def simulate_receive_transfer(amount:, currency: 'MXN', idempotency_key: nil)
72
77
  unless test_mode?
73
78
  raise Fintoc::Errors::InvalidRequestError, 'Simulation is only available in test mode'
74
79
  end
@@ -76,16 +81,16 @@ module Fintoc
76
81
  @client.simulate.receive_transfer(
77
82
  account_number_id: @id,
78
83
  amount:,
79
- currency:
84
+ currency:,
85
+ idempotency_key:
80
86
  )
81
87
  end
82
88
 
83
89
  private
84
90
 
85
91
  def refresh_from_account_number(account_number)
86
- unless account_number.id == @id
87
- raise ArgumentError, 'AccountNumber must be the same instance'
88
- end
92
+ raise ArgumentError, 'AccountNumber must be the same instance' unless
93
+ account_number.id == @id
89
94
 
90
95
  @object = account_number.object
91
96
  @description = account_number.description
@@ -97,6 +102,8 @@ module Fintoc
97
102
  @is_root = account_number.is_root
98
103
  @account_id = account_number.account_id
99
104
  @metadata = account_number.metadata
105
+ @last_transfer_at = account_number.last_transfer_at
106
+ @deleted_at = account_number.deleted_at
100
107
 
101
108
  self
102
109
  end
@@ -0,0 +1,48 @@
1
+ module Fintoc
2
+ module V2
3
+ class AccountStatement
4
+ attr_reader :id, :object, :start_date, :end_date, :total_debited_cents,
5
+ :total_credited_cents, :initial_balance_cents, :final_balance_cents,
6
+ :download_url, :created_at
7
+
8
+ def initialize(
9
+ id:,
10
+ object:,
11
+ start_date:,
12
+ end_date:,
13
+ total_debited_cents:,
14
+ total_credited_cents:,
15
+ initial_balance_cents:,
16
+ final_balance_cents:,
17
+ download_url:,
18
+ created_at:,
19
+ **
20
+ )
21
+ @id = id
22
+ @object = object
23
+ @start_date = start_date
24
+ @end_date = end_date
25
+ @total_debited_cents = total_debited_cents
26
+ @total_credited_cents = total_credited_cents
27
+ @initial_balance_cents = initial_balance_cents
28
+ @final_balance_cents = final_balance_cents
29
+ @download_url = download_url
30
+ @created_at = created_at
31
+ end
32
+
33
+ def ==(other)
34
+ @id == other.id
35
+ end
36
+
37
+ alias eql? ==
38
+
39
+ def hash
40
+ @id.hash
41
+ end
42
+
43
+ def to_s
44
+ "AccountStatement(#{@id}) #{@start_date} - #{@end_date}"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,52 @@
1
+ module Fintoc
2
+ module V2
3
+ class Movement
4
+ attr_reader :id, :object, :type, :direction, :resource_id, :mode,
5
+ :amount, :currency, :transaction_date, :return_pair_id,
6
+ :balance, :account_id
7
+
8
+ def initialize(
9
+ id:,
10
+ object:,
11
+ type:,
12
+ direction:,
13
+ mode:,
14
+ amount:,
15
+ currency:,
16
+ transaction_date:,
17
+ balance:,
18
+ account_id:,
19
+ resource_id: nil,
20
+ return_pair_id: nil,
21
+ **
22
+ )
23
+ @id = id
24
+ @object = object
25
+ @type = type
26
+ @direction = direction
27
+ @resource_id = resource_id
28
+ @mode = mode
29
+ @amount = amount
30
+ @currency = currency
31
+ @transaction_date = transaction_date
32
+ @return_pair_id = return_pair_id
33
+ @balance = balance
34
+ @account_id = account_id
35
+ end
36
+
37
+ def ==(other)
38
+ @id == other.id
39
+ end
40
+
41
+ alias eql? ==
42
+
43
+ def hash
44
+ @id.hash
45
+ end
46
+
47
+ def to_s
48
+ "#{@direction} #{@amount} #{@currency} (#{@type})"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -62,8 +62,8 @@ module Fintoc
62
62
  refresh_from_transfer(fresh_transfer)
63
63
  end
64
64
 
65
- def return_transfer
66
- returned_transfer = @client.transfers.return(@id)
65
+ def return_transfer(idempotency_key: nil)
66
+ returned_transfer = @client.transfers.return(@id, idempotency_key:)
67
67
  refresh_from_transfer(returned_transfer)
68
68
  end
69
69
 
@@ -1,3 +1,3 @@
1
1
  module Fintoc
2
- VERSION = '1.0.0'
2
+ VERSION = '1.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fintoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Ca Sardin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-08 00:00:00.000000000 Z
11
+ date: 2026-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -92,15 +92,19 @@ files:
92
92
  - lib/fintoc/v1/resources/transfer_account.rb
93
93
  - lib/fintoc/v2/client/client.rb
94
94
  - lib/fintoc/v2/managers/account_numbers_manager.rb
95
+ - lib/fintoc/v2/managers/account_statements_manager.rb
95
96
  - lib/fintoc/v2/managers/account_verifications_manager.rb
96
97
  - lib/fintoc/v2/managers/accounts_manager.rb
97
98
  - lib/fintoc/v2/managers/entities_manager.rb
99
+ - lib/fintoc/v2/managers/movements_manager.rb
98
100
  - lib/fintoc/v2/managers/simulate_manager.rb
99
101
  - lib/fintoc/v2/managers/transfers_manager.rb
100
102
  - lib/fintoc/v2/resources/account.rb
101
103
  - lib/fintoc/v2/resources/account_number.rb
104
+ - lib/fintoc/v2/resources/account_statement.rb
102
105
  - lib/fintoc/v2/resources/account_verification.rb
103
106
  - lib/fintoc/v2/resources/entity.rb
107
+ - lib/fintoc/v2/resources/movement.rb
104
108
  - lib/fintoc/v2/resources/transfer.rb
105
109
  - lib/fintoc/version.rb
106
110
  - lib/fintoc/webhook_signature.rb