From 014d7b8bddbfff64d25fe6a6b0cfda4819665e9c Mon Sep 17 00:00:00 2001 From: Juliette Date: Tue, 26 May 2026 15:05:01 -0600 Subject: [PATCH 1/5] add UpdateTransferRequest class with validation tests --- cuenca_validations/types/__init__.py | 2 ++ cuenca_validations/types/requests.py | 6 +++++- cuenca_validations/version.py | 2 +- tests/test_requests.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/cuenca_validations/types/__init__.py b/cuenca_validations/types/__init__.py index 4fbd542b..d9efe5cb 100644 --- a/cuenca_validations/types/__init__.py +++ b/cuenca_validations/types/__init__.py @@ -91,6 +91,7 @@ 'TransferNetwork', 'TransferQuery', 'TransferRequest', + 'UpdateTransferRequest', 'UserCardNotification', 'UserCredentialRequest', 'UserCredentialUpdateRequest', @@ -243,6 +244,7 @@ StrictTransferRequest, TOSRequest, TransferRequest, + UpdateTransferRequest, UserCredentialRequest, UserCredentialUpdateRequest, UserListsRequest, diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index 93c215b6..abf16eed 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -1,5 +1,5 @@ import datetime as dt -from typing import Annotated, Any, Optional, Union +from typing import Annotated, Any, Literal, Optional, Union from clabe import Clabe from pydantic import ( @@ -154,6 +154,10 @@ class StrictTransferRequest(BaseTransferRequest): ) +class UpdateTransferRequest(BaseRequest): + action: Literal['approve', 'reject'] + + class CardUpdateRequest(BaseRequest): status: Optional[CardStatus] = None pin_block: Optional[str] = None diff --git a/cuenca_validations/version.py b/cuenca_validations/version.py index 2d93b16b..b85f2215 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.32' +__version__ = '2.1.33' diff --git a/tests/test_requests.py b/tests/test_requests.py index cd6a950b..65a57a8b 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -5,6 +5,7 @@ from cuenca_validations.types.enums import VerificationType from cuenca_validations.types.requests import ( PasswordResetRequest, + UpdateTransferRequest, UserTOSAgreementRequest, UserUpdateRequest, VerificationRequest, @@ -94,3 +95,30 @@ def test_user_update_request_normalizes_email() -> None: def test_user_update_request_normalizes_phone() -> None: req = UserUpdateRequest(phone_number=PhoneNumber('+116504401222')) assert req.phone_number == '+16504401222' + + +@pytest.mark.parametrize('action', ['approve', 'reject']) +def test_update_transfer_request_valid_action(action: str) -> None: + req = UpdateTransferRequest.model_validate({'action': action}) + assert req.action == action + assert req.model_dump() == {'action': action} + + +def test_update_transfer_request_invalid_action() -> None: + with pytest.raises(ValidationError) as ex: + UpdateTransferRequest.model_validate({'action': 'cancel'}) + assert 'action' in str(ex.value) + + +def test_update_transfer_request_missing_action() -> None: + with pytest.raises(ValidationError) as ex: + UpdateTransferRequest.model_validate({}) + assert 'action' in str(ex.value) + + +def test_update_transfer_request_forbids_extra() -> None: + with pytest.raises(ValidationError) as ex: + UpdateTransferRequest.model_validate( + {'action': 'approve', 'foo': 'bar'} + ) + assert 'Extra inputs are not permitted' in str(ex.value) From 7395702acd4522d967e2479e646be8c314c243fe Mon Sep 17 00:00:00 2001 From: Juliette Date: Tue, 26 May 2026 16:50:48 -0600 Subject: [PATCH 2/5] Update version to 2.1.34 and modify UpdateTransferRequest to use status instead of action with corresponding tests --- cuenca_validations/types/requests.py | 6 +++++- cuenca_validations/version.py | 2 +- tests/test_requests.py | 25 ++++++++++++++----------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index abf16eed..ab848593 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -45,6 +45,7 @@ State, TermsOfService, TrackDataMethod, + TransactionStatus, TransactionTokenValidationStatus, UserCardNotification, UserStatus, @@ -155,7 +156,10 @@ class StrictTransferRequest(BaseTransferRequest): class UpdateTransferRequest(BaseRequest): - action: Literal['approve', 'reject'] + status: Literal[ + TransactionStatus.succeeded, + TransactionStatus.failed, + ] class CardUpdateRequest(BaseRequest): diff --git a/cuenca_validations/version.py b/cuenca_validations/version.py index b85f2215..81327732 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.33' +__version__ = '2.1.34' diff --git a/tests/test_requests.py b/tests/test_requests.py index 65a57a8b..59b729f6 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -97,28 +97,31 @@ def test_user_update_request_normalizes_phone() -> None: assert req.phone_number == '+16504401222' -@pytest.mark.parametrize('action', ['approve', 'reject']) -def test_update_transfer_request_valid_action(action: str) -> None: - req = UpdateTransferRequest.model_validate({'action': action}) - assert req.action == action - assert req.model_dump() == {'action': action} +@pytest.mark.parametrize('status', ['succeeded', 'failed']) +def test_update_transfer_request_valid_status(status: str) -> None: + req = UpdateTransferRequest.model_validate({'status': status}) + assert req.status == status + assert req.model_dump() == {'status': status} -def test_update_transfer_request_invalid_action() -> None: +@pytest.mark.parametrize( + 'status', ['created', 'submitted', 'in_review', 'cancelled'] +) +def test_update_transfer_request_invalid_status(status: str) -> None: with pytest.raises(ValidationError) as ex: - UpdateTransferRequest.model_validate({'action': 'cancel'}) - assert 'action' in str(ex.value) + UpdateTransferRequest.model_validate({'status': status}) + assert 'status' in str(ex.value) -def test_update_transfer_request_missing_action() -> None: +def test_update_transfer_request_missing_status() -> None: with pytest.raises(ValidationError) as ex: UpdateTransferRequest.model_validate({}) - assert 'action' in str(ex.value) + assert 'status' in str(ex.value) def test_update_transfer_request_forbids_extra() -> None: with pytest.raises(ValidationError) as ex: UpdateTransferRequest.model_validate( - {'action': 'approve', 'foo': 'bar'} + {'status': 'succeeded', 'foo': 'bar'} ) assert 'Extra inputs are not permitted' in str(ex.value) From 0e21429be55998dfe103f5d8afb4a4f0e140f50c Mon Sep 17 00:00:00 2001 From: Juliette Date: Wed, 27 May 2026 10:02:32 -0600 Subject: [PATCH 3/5] Refactor UpdateTransferRequest --- cuenca_validations/types/requests.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index ab848593..8788223e 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -1,5 +1,5 @@ import datetime as dt -from typing import Annotated, Any, Literal, Optional, Union +from typing import Annotated, Any, Optional, Union from clabe import Clabe from pydantic import ( @@ -156,10 +156,19 @@ class StrictTransferRequest(BaseTransferRequest): class UpdateTransferRequest(BaseRequest): - status: Literal[ - TransactionStatus.succeeded, - TransactionStatus.failed, - ] + status: TransactionStatus = Field( + description='Must be succeeded or failed', + ) + + @field_validator('status') + @classmethod + def validate_status(cls, status: TransactionStatus) -> TransactionStatus: + if status not in ( + TransactionStatus.succeeded, + TransactionStatus.failed, + ): + raise ValueError('status must be succeeded or failed') + return status class CardUpdateRequest(BaseRequest): From 088594f553e10bf10d79cc88c906121a93c83cf4 Mon Sep 17 00:00:00 2001 From: Juliette Date: Wed, 27 May 2026 12:10:48 -0600 Subject: [PATCH 4/5] Refactor UpdateTransferRequest to simplify status definition and update related tests for valid and invalid statuses --- cuenca_validations/types/requests.py | 4 +--- tests/test_requests.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index 8788223e..67f0cf84 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -156,9 +156,7 @@ class StrictTransferRequest(BaseTransferRequest): class UpdateTransferRequest(BaseRequest): - status: TransactionStatus = Field( - description='Must be succeeded or failed', - ) + status: TransactionStatus @field_validator('status') @classmethod diff --git a/tests/test_requests.py b/tests/test_requests.py index 59b729f6..aba93592 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -104,9 +104,7 @@ def test_update_transfer_request_valid_status(status: str) -> None: assert req.model_dump() == {'status': status} -@pytest.mark.parametrize( - 'status', ['created', 'submitted', 'in_review', 'cancelled'] -) +@pytest.mark.parametrize('status', ['created', 'submitted', 'in_review']) def test_update_transfer_request_invalid_status(status: str) -> None: with pytest.raises(ValidationError) as ex: UpdateTransferRequest.model_validate({'status': status}) From f554ff4b43442183ed4b01abd7f5d0e2f4a0de8d Mon Sep 17 00:00:00 2001 From: Juliette Date: Wed, 27 May 2026 12:12:41 -0600 Subject: [PATCH 5/5] Update version to 2.1.35 --- cuenca_validations/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuenca_validations/version.py b/cuenca_validations/version.py index 81327732..0433f6dd 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.34' +__version__ = '2.1.35'