Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions cuenca/resources/transfers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
from typing import ClassVar, Optional, cast

from cuenca_validations.types import (
TransactionStatus,
TransferNetwork,
TransferQuery,
TransferRequest,
UpdateTransferRequest,
)
from cuenca_validations.typing import DictStrAny
from requests import HTTPError

from ..exc import CuencaException
from ..http import Session, session as global_session
from .accounts import Account
from .base import Creatable, Transaction
from .base import Creatable, Transaction, Updateable
from .resources import retrieve_uri


class Transfer(Transaction, Creatable):
class Transfer(Transaction, Creatable, Updateable):
_resource: ClassVar = 'transfers'
_query_params: ClassVar = TransferQuery

Expand Down Expand Up @@ -71,6 +74,17 @@ def create(
)
return cls._create(**req.model_dump())

@classmethod
def update(
cls,
transfer_id: str,
status: TransactionStatus,
*,
session: Session = global_session,
) -> 'Transfer':
req = UpdateTransferRequest(status=status)
return cls._update(transfer_id, session=session, **req.model_dump())

@classmethod
def create_many(cls, requests: list[TransferRequest]) -> DictStrAny:
transfers: DictStrAny = dict(submitted=[], errors=[])
Expand Down
2 changes: 1 addition & 1 deletion cuenca/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = '2.2.0'
__version__ = '2.2.1'
CLIENT_VERSION = __version__
API_VERSION = '2020-03-19'
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
requests==2.32.3
cuenca-validations==2.1.31
cuenca-validations==2.1.34
pydantic-extra-types==2.10.2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
python_requires='>=3.9',
install_requires=[
'requests>=2.32.0',
'cuenca-validations>=2.1.27',
'cuenca-validations>=2.1.34',
'pydantic-extra-types>=2.10.0',
],
classifiers=[
Expand Down
35 changes: 35 additions & 0 deletions tests/resources/cassettes/test_transfers_update_failed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
interactions:
- request:
body: '{"status": "failed"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- DUMMY
Connection:
- keep-alive
Content-Length:
- '20'
Content-Type:
- application/json
User-Agent:
- cuenca-python/2.2.1
X-Cuenca-Api-Version:
- '2020-03-19'
method: PATCH
uri: https://sandbox.cuenca.com/transfers/TR02
response:
body:
string: '{"id":"TR02","created_at":"2026-05-26T12:00:00.000000","updated_at":"2026-05-26T12:02:00.000000","account_number":"646180157046685645","recipient_name":"Rogelio
Lopez","amount":10000,"descriptor":"held transfer","idempotency_key":"idem-tr02","status":"failed","network":"internal","destination_uri":"/accounts/LA1CVCZVNLR4KM42kPcqhBLV","tracking_key":null,"user_id":"US4PCNV8rLB2wqBfORzIAXUl","reference_number":null}'
headers:
Connection:
- keep-alive
Content-Type:
- application/json
status:
code: 200
message: OK
version: 1
35 changes: 35 additions & 0 deletions tests/resources/cassettes/test_transfers_update_succeeded.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
interactions:
- request:
body: '{"status": "succeeded"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- DUMMY
Connection:
- keep-alive
Content-Length:
- '23'
Content-Type:
- application/json
User-Agent:
- cuenca-python/2.2.1
X-Cuenca-Api-Version:
- '2020-03-19'
method: PATCH
uri: https://sandbox.cuenca.com/transfers/TR01
response:
body:
string: '{"id":"TR01","created_at":"2026-05-26T12:00:00.000000","updated_at":"2026-05-26T12:01:00.000000","account_number":"646180157046685645","recipient_name":"Rogelio
Lopez","amount":10000,"descriptor":"held transfer","idempotency_key":"idem-tr01","status":"succeeded","network":"internal","destination_uri":"/accounts/LA1CVCZVNLR4KM42kPcqhBLV","tracking_key":"tk01","user_id":"US4PCNV8rLB2wqBfORzIAXUl","reference_number":null}'
headers:
Connection:
- keep-alive
Content-Type:
- application/json
status:
code: 200
message: OK
version: 1
30 changes: 30 additions & 0 deletions tests/resources/test_transfers.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,33 @@ def test_invalid_params():
with pytest.raises(ValidationError) as e:
Transfer.one(invalid_param='invalid_param')
assert 'Extra inputs are not permitted' in str(e)


@pytest.mark.vcr
def test_transfers_update_succeeded():
transfer = Transfer.update('TR01', status=TransactionStatus.succeeded)
assert transfer.id == 'TR01'
assert transfer.status == TransactionStatus.succeeded


@pytest.mark.vcr
def test_transfers_update_failed():
transfer = Transfer.update('TR02', status=TransactionStatus.failed)
assert transfer.id == 'TR02'
assert transfer.status == TransactionStatus.failed


@pytest.mark.parametrize(
'invalid_status',
[
TransactionStatus.created,
TransactionStatus.submitted,
TransactionStatus.in_review,
'cancelled',
'approve',
'reject',
],
)
def test_transfers_update_rejects_invalid_status(invalid_status):
with pytest.raises(ValidationError):
Transfer.update('TR03', status=invalid_status)
Loading