From 05bbaaf5a6c5f45399a082f81f459d099f6a3010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Cabrera?= Date: Thu, 27 Aug 2026 17:22:39 -0600 Subject: [PATCH 1/8] feat: add account and operational event types Types for oaxaca beneficiaries (#605) and audit log (#608). Co-authored-by: Cursor --- cuenca_validations/types/__init__.py | 14 ++++++++++-- cuenca_validations/types/enums.py | 12 ++++++++++ cuenca_validations/types/queries.py | 6 +++++ cuenca_validations/types/requests.py | 34 ++++++++++++++++++++++++++++ cuenca_validations/version.py | 2 +- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/cuenca_validations/types/__init__.py b/cuenca_validations/types/__init__.py index 045fc9b6..60b9f34a 100644 --- a/cuenca_validations/types/__init__.py +++ b/cuenca_validations/types/__init__.py @@ -1,6 +1,9 @@ __all__ = [ 'AccountUseType', 'AccountQuery', + 'AccountRequest', + 'AccountUpdateRequest', + 'AccountValidationStatus', 'Address', 'AgentQuery', 'AgentRequest', @@ -57,11 +60,13 @@ 'KYCValidationRequest', 'KYCValidationSource', 'Language', + 'LegalPersonRequest', + 'LegalPersonUpdateRequest', 'LimitedWalletRequest', 'MonthlyMovementsType', 'MonthlySpendingType', - 'LegalPersonRequest', - 'LegalPersonUpdateRequest', + 'OperationalEventAction', + 'OperationalEventQuery', 'PartnerRequest', 'PartnerUpdateRequest', 'PasswordResetRequest', @@ -132,6 +137,7 @@ from .card import StrictPaymentCardNumber from .enums import ( AccountUseType, + AccountValidationStatus, AuthorizerTransaction, BankAccountStatus, CardErrorType, @@ -158,6 +164,7 @@ Language, MonthlyMovementsType, MonthlySpendingType, + OperationalEventAction, PlatformType, PosCapability, Profession, @@ -216,6 +223,7 @@ EventQuery, FileQuery, IdentityQuery, + OperationalEventQuery, PostalCodeQuery, QueryParams, SessionQuery, @@ -229,6 +237,8 @@ WalletTransactionQuery, ) from .requests import ( + AccountRequest, + AccountUpdateRequest, AgentRequest, ApiKeyUpdateRequest, BankAccountValidationRequest, diff --git a/cuenca_validations/types/enums.py b/cuenca_validations/types/enums.py index 6da7bc8b..b3356f69 100644 --- a/cuenca_validations/types/enums.py +++ b/cuenca_validations/types/enums.py @@ -745,3 +745,15 @@ class RequiredAction(str, Enum): level_up_required = 'level_up_required' level_up_invitation = 'level_up_invitation' fix_documents = 'fix_documents' + + +class AccountValidationStatus(str, Enum): + verified = 'verified' + pending = 'pending' + + +class OperationalEventAction(str, Enum): + account_created = 'account_created' + account_updated = 'account_updated' + transfer_created = 'transfer_created' + statement_downloaded = 'statement_downloaded' diff --git a/cuenca_validations/types/queries.py b/cuenca_validations/types/queries.py index 5981c269..d0c6b6e2 100644 --- a/cuenca_validations/types/queries.py +++ b/cuenca_validations/types/queries.py @@ -22,6 +22,7 @@ CardType, EventType, KYCFileType, + OperationalEventAction, SessionType, TermsOfService, TransferNetwork, @@ -153,6 +154,11 @@ class AccountQuery(QueryParams): account_number: Optional[str] = None +class OperationalEventQuery(QueryParams): + actor_id: Optional[str] = None + action: Optional[OperationalEventAction] = None + + class BalanceEntryQuery(QueryParams): funding_instrument_uri: Optional[str] = None wallet_id: str = 'default' diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index ffbf867b..ff21fdc4 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -18,6 +18,7 @@ from ..types.enums import ( AccountUseType, + AccountValidationStatus, AuthorizerTransaction, CardDesign, CardFundingType, @@ -735,6 +736,39 @@ class LimitedWalletRequest(BaseRequest): allowed_rfc: Optional[Rfc] = None +class AccountRequest(BaseRequest): + name: StrictStr + account_number: Clabe + alias: Optional[StrictStr] = None + curp: Optional[Curp] = None + rfc: Optional[Rfc] = None + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'name': 'Aceros del Norte SA de CV', + 'account_number': '072691004495711499', + 'alias': 'Proveedor acero', + } + }, + ) + + +class AccountUpdateRequest(BaseRequest): + name: Optional[StrictStr] = None + alias: Optional[StrictStr] = None + validation_status: Optional[AccountValidationStatus] = None + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'alias': 'Fletes', + 'validation_status': 'verified', + } + }, + ) + + class PlatformRequest(BaseModel): name: str rfc: Optional[str] = None diff --git a/cuenca_validations/version.py b/cuenca_validations/version.py index 9f552eb9..249b12c1 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.42' +__version__ = '2.1.43.dev0' From 8d27d6c19c32d31d41de23f027d6aa07fd5f1cb3 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Tue, 1 Sep 2026 21:59:23 +0100 Subject: [PATCH 2/8] feat: introduce operator and moral person request types --- cuenca_validations/types/__init__.py | 12 +++ cuenca_validations/types/enums.py | 10 ++ cuenca_validations/types/requests.py | 94 +++++++++++++++++++ tests/test_requests.py | 135 ++++++++++++++++++++++++++- 4 files changed, 250 insertions(+), 1 deletion(-) diff --git a/cuenca_validations/types/__init__.py b/cuenca_validations/types/__init__.py index 60b9f34a..e7a0078d 100644 --- a/cuenca_validations/types/__init__.py +++ b/cuenca_validations/types/__init__.py @@ -67,6 +67,12 @@ 'MonthlySpendingType', 'OperationalEventAction', 'OperationalEventQuery', + 'OperatorLoginRequest', + 'OperatorLoginResponse', + 'OperatorRequest', + 'OperatorRole', + 'OperatorStatus', + 'OperatorUpdateRequest', 'PartnerRequest', 'PartnerUpdateRequest', 'PasswordResetRequest', @@ -165,6 +171,8 @@ MonthlyMovementsType, MonthlySpendingType, OperationalEventAction, + OperatorRole, + OperatorStatus, PlatformType, PosCapability, Profession, @@ -254,6 +262,10 @@ LegalPersonRequest, LegalPersonUpdateRequest, LimitedWalletRequest, + OperatorLoginRequest, + OperatorLoginResponse, + OperatorRequest, + OperatorUpdateRequest, PartnerRequest, PartnerUpdateRequest, PasswordResetRequest, diff --git a/cuenca_validations/types/enums.py b/cuenca_validations/types/enums.py index b3356f69..098cb020 100644 --- a/cuenca_validations/types/enums.py +++ b/cuenca_validations/types/enums.py @@ -757,3 +757,13 @@ class OperationalEventAction(str, Enum): account_updated = 'account_updated' transfer_created = 'transfer_created' statement_downloaded = 'statement_downloaded' + + +class OperatorRole(str, Enum): + operator = 'operator' + authorizer = 'authorizer' + + +class OperatorStatus(str, Enum): + active = 'active' + disabled = 'disabled' diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index ff21fdc4..5c6d9c9d 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -37,6 +37,8 @@ KYCValidationSource, MonthlyMovementsType, MonthlySpendingType, + OperatorRole, + OperatorStatus, PlatformType, PosCapability, Profession, @@ -925,6 +927,13 @@ class LegalPersonRequest(BaseRequest): }, ) + @field_validator('rfc') + @classmethod + def validate_legal_rfc(cls, rfc: Rfc) -> Rfc: + if len(rfc) != 12: + raise ValueError('RFC must be 12 characters for legal persons') + return rfc + class LegalPersonUpdateRequest(BaseRequest): legal_name: Optional[str] = None @@ -932,6 +941,91 @@ class LegalPersonUpdateRequest(BaseRequest): address: Optional[AddressRequest] = None legal_representatives: Optional[list[LegalRepresentative]] = None + @model_validator(mode="before") + @classmethod + def check_at_least_one_param(cls, values: DictStrAny) -> DictStrAny: + if not values: + raise ValueError('At least one parameter must be provided') + return values + + @field_validator('rfc') + @classmethod + def validate_legal_rfc(cls, rfc: Optional[Rfc]) -> Optional[Rfc]: + if rfc is not None and len(rfc) != 12: + raise ValueError('RFC must be 12 characters for legal persons') + return rfc + + +class OperatorRequest(BaseRequest): + name: str + email: EmailStr + phone: PhoneNumber + company_user_id: str + role: OperatorRole + status: OperatorStatus = OperatorStatus.active + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'name': 'Maria Lopez', + 'email': 'maria.lopez@aceros.com', + 'phone': '+525512345678', + 'company_user_id': 'USWqY5cvkISJOxHyEKjAKf8w', + 'role': 'operator', + } + }, + ) + + @field_validator('email', mode='before') + @classmethod + def validate_email(cls, email: str) -> str: + return normalize_email(email) + + +class OperatorUpdateRequest(BaseRequest): + name: Optional[str] = None + phone: Optional[PhoneNumber] = None + role: Optional[OperatorRole] = None + status: Optional[OperatorStatus] = None + + @model_validator(mode="before") + @classmethod + def check_at_least_one_param(cls, values: DictStrAny) -> DictStrAny: + if not values: + raise ValueError('At least one parameter must be provided') + return values + + +class OperatorLoginRequest(BaseRequest): + email: EmailStr + password: Annotated[Password, LogConfig(masked=True)] + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'email': 'maria.lopez@aceros.com', + 'password': 'supersecret', + } + }, + ) + + @field_validator('email', mode='before') + @classmethod + def validate_email(cls, email: str) -> str: + return normalize_email(email) + + +class OperatorLoginResponse(BaseModel): + session_token: str + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'session_token': 'SEWqY5cvkISJOxHyEKjAKf8w', + } + }, + ) + class PhoneVerificationAssociationRequest(BaseRequest): verification_id: str diff --git a/tests/test_requests.py b/tests/test_requests.py index d756be59..322801b4 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2,8 +2,19 @@ from pydantic import ValidationError from pydantic_extra_types.phone_numbers import PhoneNumber -from cuenca_validations.types.enums import Country, VerificationType +from cuenca_validations.types.enums import ( + Country, + OperatorRole, + OperatorStatus, + VerificationType, +) from cuenca_validations.types.requests import ( + LegalPersonRequest, + LegalPersonUpdateRequest, + OperatorLoginRequest, + OperatorLoginResponse, + OperatorRequest, + OperatorUpdateRequest, PasswordResetRequest, UpdateTransferRequest, UserTOSAgreementRequest, @@ -12,6 +23,128 @@ ) from cuenca_validations.typing import DictStrAny +LEGAL_REPRESENTATIVE: DictStrAny = { + 'names': 'Juan', + 'first_surname': 'Perez', + 'job': 'Director General', + 'phone_number': '+525512345678', + 'email_address': 'juan.perez@aceros.com', + 'address': { + 'street': 'Reforma', + 'ext_number': '265', + 'postal_code_id': 'PC2ygq9j2bS9-9tsuVawzErA', + }, +} + +LEGAL_PERSON_REQUEST: DictStrAny = { + 'legal_name': 'Aceros del Norte SA de CV', + 'rfc': 'ADN850101ABC', + 'address': { + 'street': 'Reforma', + 'ext_number': '265', + 'postal_code_id': 'PC2ygq9j2bS9-9tsuVawzErA', + }, + 'legal_representatives': [LEGAL_REPRESENTATIVE], +} + + +def test_legal_person_request_valid() -> None: + req = LegalPersonRequest.model_validate(LEGAL_PERSON_REQUEST) + assert req.legal_name == 'Aceros del Norte SA de CV' + assert req.rfc == 'ADN850101ABC' + + +def test_legal_person_request_rejects_physical_rfc() -> None: + with pytest.raises(ValidationError) as ex: + LegalPersonRequest.model_validate( + {**LEGAL_PERSON_REQUEST, 'rfc': 'GOCG650418TJ1'} + ) + assert 'RFC must be 12 characters for legal persons' in str(ex.value) + + +def test_legal_person_request_forbids_extra() -> None: + with pytest.raises(ValidationError) as ex: + LegalPersonRequest.model_validate( + {**LEGAL_PERSON_REQUEST, 'foo': 'bar'} + ) + assert 'Extra inputs are not permitted' in str(ex.value) + + +def test_legal_person_update_requires_at_least_one_param() -> None: + with pytest.raises(ValueError) as ex: + LegalPersonUpdateRequest() + assert 'At least one parameter must be provided' in str(ex.value) + + +def test_operator_request_valid() -> None: + req = OperatorRequest( + name='Maria Lopez', + email='Maria+Tag@Aceros.com', + phone=PhoneNumber('+525512345678'), + company_user_id='USWqY5cvkISJOxHyEKjAKf8w', + role=OperatorRole.operator, + ) + assert req.email == 'maria@aceros.com' + assert req.status == OperatorStatus.active + + +def test_operator_request_rejects_invalid_role() -> None: + with pytest.raises(ValidationError) as ex: + OperatorRequest.model_validate( + { + 'name': 'Maria Lopez', + 'email': 'maria@aceros.com', + 'phone': '+525512345678', + 'company_user_id': 'USWqY5cvkISJOxHyEKjAKf8w', + 'role': 'admin', + } + ) + assert 'role' in str(ex.value) + + +def test_operator_update_requires_at_least_one_param() -> None: + with pytest.raises(ValueError) as ex: + OperatorUpdateRequest() + assert 'At least one parameter must be provided' in str(ex.value) + + +def test_operator_login_request_valid() -> None: + req = OperatorLoginRequest.model_validate( + { + 'email': 'Operator+Tag@Aceros.com', + 'password': 'supersecret', + } + ) + assert req.email == 'operator@aceros.com' + + +def test_operator_login_request_rejects_short_password() -> None: + with pytest.raises(ValidationError) as ex: + OperatorLoginRequest.model_validate( + { + 'email': 'operator@aceros.com', + 'password': 'short', + } + ) + assert 'password' in str(ex.value) + + +def test_operator_login_request_forbids_extra() -> None: + with pytest.raises(ValidationError) as ex: + OperatorLoginRequest.model_validate( + { + 'email': 'operator@aceros.com', + 'password': 'supersecret', + 'foo': 'bar', + } + ) + assert 'Extra inputs are not permitted' in str(ex.value) + + +def test_operator_login_response_valid() -> None: + resp = OperatorLoginResponse(session_token='SEWqY5cvkISJOxHyEKjAKf8w') + assert resp.session_token == 'SEWqY5cvkISJOxHyEKjAKf8w' + @pytest.mark.parametrize('environment', ['api.stage', 'api.sandbox', 'api']) def test_file_cuenca_url(environment: str) -> None: From d09f50e69d5f6b6cb08c65bbbe65d64b1db2ffb5 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Tue, 1 Sep 2026 22:08:31 +0100 Subject: [PATCH 3/8] feat: add tests for moral and operator person update requests --- tests/test_requests.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index 322801b4..ce2f6808 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -76,6 +76,22 @@ def test_legal_person_update_requires_at_least_one_param() -> None: assert 'At least one parameter must be provided' in str(ex.value) +def test_moral_person_update_valid() -> None: + req = MoralPersonUpdateRequest.model_validate({'legal_name': 'New name'}) + assert req.legal_name == 'New name' + + +def test_moral_person_update_accepts_moral_rfc() -> None: + req = MoralPersonUpdateRequest.model_validate({'rfc': 'ADN850101ABC'}) + assert req.rfc == 'ADN850101ABC' + + +def test_moral_person_update_rejects_physical_rfc() -> None: + with pytest.raises(ValidationError) as ex: + MoralPersonUpdateRequest.model_validate({'rfc': 'GOCG650418TJ1'}) + assert 'RFC must be 12 characters for moral persons' in str(ex.value) + + def test_operator_request_valid() -> None: req = OperatorRequest( name='Maria Lopez', @@ -108,6 +124,11 @@ def test_operator_update_requires_at_least_one_param() -> None: assert 'At least one parameter must be provided' in str(ex.value) +def test_operator_update_valid() -> None: + req = OperatorUpdateRequest.model_validate({'name': 'New name'}) + assert req.name == 'New name' + + def test_operator_login_request_valid() -> None: req = OperatorLoginRequest.model_validate( { From 125d8804539994a7f3537402ed4d284a3114b033 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Wed, 2 Sep 2026 00:39:52 +0100 Subject: [PATCH 4/8] feat: add OperatorQuery and SessionMetadata types with corresponding SessionResponse updates --- cuenca_validations/types/__init__.py | 6 +++++ cuenca_validations/types/queries.py | 4 ++++ cuenca_validations/types/requests.py | 18 ++++++++++++++ tests/test_requests.py | 35 ++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/cuenca_validations/types/__init__.py b/cuenca_validations/types/__init__.py index e7a0078d..c59c9b9a 100644 --- a/cuenca_validations/types/__init__.py +++ b/cuenca_validations/types/__init__.py @@ -69,6 +69,7 @@ 'OperationalEventQuery', 'OperatorLoginRequest', 'OperatorLoginResponse', + 'OperatorQuery', 'OperatorRequest', 'OperatorRole', 'OperatorStatus', @@ -91,8 +92,10 @@ 'SavingRequest', 'SavingUpdateRequest', 'ServiceProviderCategory', + 'SessionMetadata', 'SessionQuery', 'SessionRequest', + 'SessionResponse', 'SessionType', 'State', 'StatementQuery', @@ -232,6 +235,7 @@ FileQuery, IdentityQuery, OperationalEventQuery, + OperatorQuery, PostalCodeQuery, QueryParams, SessionQuery, @@ -273,7 +277,9 @@ QuestionnairesRequest, SavingRequest, SavingUpdateRequest, + SessionMetadata, SessionRequest, + SessionResponse, StrictTransferRequest, TOSRequest, TransferRequest, diff --git a/cuenca_validations/types/queries.py b/cuenca_validations/types/queries.py index d0c6b6e2..c5e794f7 100644 --- a/cuenca_validations/types/queries.py +++ b/cuenca_validations/types/queries.py @@ -159,6 +159,10 @@ class OperationalEventQuery(QueryParams): action: Optional[OperationalEventAction] = None +class OperatorQuery(QueryParams): + email: Optional[EmailStr] = None + + class BalanceEntryQuery(QueryParams): funding_instrument_uri: Optional[str] = None wallet_id: str = 'default' diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index 5c6d9c9d..d64c3b68 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -632,11 +632,29 @@ class UserLoginRequest(BaseRequest): ) +class SessionMetadata(BaseModel): + operator_id: Optional[str] = None + model_config = ConfigDict(extra='forbid') + + +class SessionResponse(BaseModel): + id: str + created_at: dt.datetime + user_id: str + platform_id: str + expires_at: dt.datetime + type: SessionType + success_url: Optional[SerializableAnyUrl] = None + failure_url: Optional[SerializableAnyUrl] = None + metadata: Optional[SessionMetadata] = None + + class SessionRequest(BaseRequest): user_id: str type: SessionType success_url: Optional[SerializableAnyUrl] = None failure_url: Optional[SerializableAnyUrl] = None + metadata: Optional[SessionMetadata] = None model_config = ConfigDict( json_schema_extra={ 'example': { diff --git a/tests/test_requests.py b/tests/test_requests.py index ce2f6808..c804a6b1 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -6,8 +6,10 @@ Country, OperatorRole, OperatorStatus, + SessionType, VerificationType, ) +from cuenca_validations.types.queries import OperatorQuery from cuenca_validations.types.requests import ( LegalPersonRequest, LegalPersonUpdateRequest, @@ -16,6 +18,8 @@ OperatorRequest, OperatorUpdateRequest, PasswordResetRequest, + SessionMetadata, + SessionRequest, UpdateTransferRequest, UserTOSAgreementRequest, UserUpdateRequest, @@ -167,6 +171,37 @@ def test_operator_login_response_valid() -> None: assert resp.session_token == 'SEWqY5cvkISJOxHyEKjAKf8w' +def test_operator_query_valid() -> None: + query = OperatorQuery.model_validate({'email': 'maria.lopez@aceros.com'}) + assert str(query.email) == 'maria.lopez@aceros.com' + + +def test_operator_query_forbids_extra() -> None: + with pytest.raises(ValidationError) as ex: + OperatorQuery.model_validate( + {'email': 'maria@aceros.com', 'foo': 'bar'} + ) + assert 'Extra inputs are not permitted' in str(ex.value) + + +def test_session_request_with_operator_metadata() -> None: + req = SessionRequest( + user_id='USWqY5cvkISJOxHyEKjAKf8w', + type=SessionType.registration, + metadata=SessionMetadata(operator_id='OPWqY5cvkISJOxHyEKjAKf8w'), + ) + assert req.metadata is not None + assert req.metadata.operator_id == 'OPWqY5cvkISJOxHyEKjAKf8w' + + +def test_session_request_metadata_forbids_extra() -> None: + with pytest.raises(ValidationError) as ex: + SessionMetadata.model_validate( + {'operator_id': 'OPWqY5cvkISJOxHyEKjAKf8w', 'foo': 'bar'} + ) + assert 'Extra inputs are not permitted' in str(ex.value) + + @pytest.mark.parametrize('environment', ['api.stage', 'api.sandbox', 'api']) def test_file_cuenca_url(environment: str) -> None: request_data: DictStrAny = dict( From 96c53cb8a9a8f4385a904f040ecc4df113a42fa3 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Wed, 2 Sep 2026 18:12:23 +0100 Subject: [PATCH 5/8] feat: rename MoralPersonRequest and MoralPersonUpdateRequest to LegalPersonRequest and LegalPersonUpdateRequest, updating validations and tests accordingly --- tests/test_requests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index c804a6b1..c9dae3dd 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -80,20 +80,20 @@ def test_legal_person_update_requires_at_least_one_param() -> None: assert 'At least one parameter must be provided' in str(ex.value) -def test_moral_person_update_valid() -> None: - req = MoralPersonUpdateRequest.model_validate({'legal_name': 'New name'}) +def test_legal_person_update_valid() -> None: + req = LegalPersonUpdateRequest.model_validate({'legal_name': 'New name'}) assert req.legal_name == 'New name' -def test_moral_person_update_accepts_moral_rfc() -> None: - req = MoralPersonUpdateRequest.model_validate({'rfc': 'ADN850101ABC'}) +def test_legal_person_update_accepts_legal_rfc() -> None: + req = LegalPersonUpdateRequest.model_validate({'rfc': 'ADN850101ABC'}) assert req.rfc == 'ADN850101ABC' -def test_moral_person_update_rejects_physical_rfc() -> None: +def test_legal_person_update_rejects_physical_rfc() -> None: with pytest.raises(ValidationError) as ex: - MoralPersonUpdateRequest.model_validate({'rfc': 'GOCG650418TJ1'}) - assert 'RFC must be 12 characters for moral persons' in str(ex.value) + LegalPersonUpdateRequest.model_validate({'rfc': 'GOCG650418TJ1'}) + assert 'RFC must be 12 characters for legal persons' in str(ex.value) def test_operator_request_valid() -> None: From 9534eb74c8d4333536bb34b79dd918dd67571c8d Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Fri, 4 Sep 2026 21:55:48 +0100 Subject: [PATCH 6/8] chore: update version to 2.1.41.dev4 Co-authored-by: Cursor --- 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 249b12c1..834b8505 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.43.dev0' +__version__ = '2.1.41.dev4' From 9d8d3c753324a1878a09bf48c76bdc5dbba322e3 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Sun, 6 Sep 2026 22:28:12 +0100 Subject: [PATCH 7/8] feat: enhance OperatorLoginResponse with additional fields --- cuenca_validations/types/requests.py | 6 ++++++ tests/test_requests.py | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cuenca_validations/types/requests.py b/cuenca_validations/types/requests.py index d64c3b68..c0a5e721 100644 --- a/cuenca_validations/types/requests.py +++ b/cuenca_validations/types/requests.py @@ -1035,11 +1035,17 @@ def validate_email(cls, email: str) -> str: class OperatorLoginResponse(BaseModel): session_token: str + operator_id: str + role: OperatorRole + company_user_id: str model_config = ConfigDict( json_schema_extra={ 'example': { 'session_token': 'SEWqY5cvkISJOxHyEKjAKf8w', + 'operator_id': 'OPWqY5cvkISJOxHyEKjAKf8w', + 'role': 'authorizer', + 'company_user_id': 'USWqY5cvkISJOxHyEKjAKf8w', } }, ) diff --git a/tests/test_requests.py b/tests/test_requests.py index c9dae3dd..b081e7a4 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -167,8 +167,16 @@ def test_operator_login_request_forbids_extra() -> None: def test_operator_login_response_valid() -> None: - resp = OperatorLoginResponse(session_token='SEWqY5cvkISJOxHyEKjAKf8w') + resp = OperatorLoginResponse( + session_token='SEWqY5cvkISJOxHyEKjAKf8w', + operator_id='OPWqY5cvkISJOxHyEKjAKf8w', + role=OperatorRole.authorizer, + company_user_id='USWqY5cvkISJOxHyEKjAKf8w', + ) assert resp.session_token == 'SEWqY5cvkISJOxHyEKjAKf8w' + assert resp.operator_id == 'OPWqY5cvkISJOxHyEKjAKf8w' + assert resp.role == OperatorRole.authorizer + assert resp.company_user_id == 'USWqY5cvkISJOxHyEKjAKf8w' def test_operator_query_valid() -> None: From f0477bfadae01ef5667824aeb6f8e5bc3a93d777 Mon Sep 17 00:00:00 2001 From: Juliette Trejo Ceballos Date: Sun, 6 Sep 2026 22:31:07 +0100 Subject: [PATCH 8/8] chore: update version to 2.1.41.dev5 Co-authored-by: Cursor --- 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 834b8505..d1c239a9 100644 --- a/cuenca_validations/version.py +++ b/cuenca_validations/version.py @@ -1 +1 @@ -__version__ = '2.1.41.dev4' +__version__ = '2.1.41.dev5'