cuenca-validations 2.1.40.dev1__tar.gz → 2.1.41.dev1__tar.gz
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.
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/PKG-INFO +1 -1
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/__init__.py +26 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/enums.py +22 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/queries.py +6 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/requests.py +161 -0
- cuenca_validations-2.1.41.dev1/cuenca_validations/version.py +1 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations.egg-info/PKG-INFO +1 -1
- cuenca_validations-2.1.41.dev1/tests/test_requests.py +279 -0
- cuenca_validations-2.1.40.dev1/cuenca_validations/version.py +0 -1
- cuenca_validations-2.1.40.dev1/tests/test_requests.py +0 -130
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/LICENSE +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/README.md +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/__init__.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/card_bins.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/errors.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/py.typed +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/card.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/files.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/general.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/helpers.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/identities.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/morals.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/typing.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/validators.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations.egg-info/SOURCES.txt +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations.egg-info/dependency_links.txt +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations.egg-info/requires.txt +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations.egg-info/top_level.txt +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/setup.cfg +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/setup.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/__init__.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_card.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_errors.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_helpers.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_statement.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_types.py +0 -0
- {cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/tests/test_validators.py +0 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
__all__ = [
|
|
2
2
|
'AccountUseType',
|
|
3
3
|
'AccountQuery',
|
|
4
|
+
'AccountRequest',
|
|
5
|
+
'AccountUpdateRequest',
|
|
6
|
+
'AccountValidationStatus',
|
|
4
7
|
'Address',
|
|
5
8
|
'AgentQuery',
|
|
6
9
|
'AgentRequest',
|
|
@@ -60,6 +63,16 @@ __all__ = [
|
|
|
60
63
|
'LimitedWalletRequest',
|
|
61
64
|
'MonthlyMovementsType',
|
|
62
65
|
'MonthlySpendingType',
|
|
66
|
+
'MoralPersonRequest',
|
|
67
|
+
'MoralPersonUpdateRequest',
|
|
68
|
+
'OperationalEventAction',
|
|
69
|
+
'OperationalEventQuery',
|
|
70
|
+
'OperatorLoginRequest',
|
|
71
|
+
'OperatorLoginResponse',
|
|
72
|
+
'OperatorRequest',
|
|
73
|
+
'OperatorRole',
|
|
74
|
+
'OperatorStatus',
|
|
75
|
+
'OperatorUpdateRequest',
|
|
63
76
|
'PartnerRequest',
|
|
64
77
|
'PartnerUpdateRequest',
|
|
65
78
|
'PasswordResetRequest',
|
|
@@ -129,6 +142,7 @@ __all__ = [
|
|
|
129
142
|
from .card import StrictPaymentCardNumber
|
|
130
143
|
from .enums import (
|
|
131
144
|
AccountUseType,
|
|
145
|
+
AccountValidationStatus,
|
|
132
146
|
AuthorizerTransaction,
|
|
133
147
|
BankAccountStatus,
|
|
134
148
|
CardErrorType,
|
|
@@ -155,6 +169,9 @@ from .enums import (
|
|
|
155
169
|
Language,
|
|
156
170
|
MonthlyMovementsType,
|
|
157
171
|
MonthlySpendingType,
|
|
172
|
+
OperationalEventAction,
|
|
173
|
+
OperatorRole,
|
|
174
|
+
OperatorStatus,
|
|
158
175
|
PlatformType,
|
|
159
176
|
PosCapability,
|
|
160
177
|
Profession,
|
|
@@ -213,6 +230,7 @@ from .queries import (
|
|
|
213
230
|
EventQuery,
|
|
214
231
|
FileQuery,
|
|
215
232
|
IdentityQuery,
|
|
233
|
+
OperationalEventQuery,
|
|
216
234
|
PostalCodeQuery,
|
|
217
235
|
QueryParams,
|
|
218
236
|
SessionQuery,
|
|
@@ -226,6 +244,8 @@ from .queries import (
|
|
|
226
244
|
WalletTransactionQuery,
|
|
227
245
|
)
|
|
228
246
|
from .requests import (
|
|
247
|
+
AccountRequest,
|
|
248
|
+
AccountUpdateRequest,
|
|
229
249
|
AgentRequest,
|
|
230
250
|
ApiKeyUpdateRequest,
|
|
231
251
|
BankAccountValidationRequest,
|
|
@@ -239,6 +259,12 @@ from .requests import (
|
|
|
239
259
|
FraudFundsTransferRequest,
|
|
240
260
|
KYCValidationRequest,
|
|
241
261
|
LimitedWalletRequest,
|
|
262
|
+
MoralPersonRequest,
|
|
263
|
+
MoralPersonUpdateRequest,
|
|
264
|
+
OperatorLoginRequest,
|
|
265
|
+
OperatorLoginResponse,
|
|
266
|
+
OperatorRequest,
|
|
267
|
+
OperatorUpdateRequest,
|
|
242
268
|
PartnerRequest,
|
|
243
269
|
PartnerUpdateRequest,
|
|
244
270
|
PasswordResetRequest,
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/enums.py
RENAMED
|
@@ -744,3 +744,25 @@ class RequiredAction(str, Enum):
|
|
|
744
744
|
level_up_required = 'level_up_required'
|
|
745
745
|
level_up_invitation = 'level_up_invitation'
|
|
746
746
|
fix_documents = 'fix_documents'
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
class AccountValidationStatus(str, Enum):
|
|
750
|
+
verified = 'verified'
|
|
751
|
+
pending = 'pending'
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
class OperationalEventAction(str, Enum):
|
|
755
|
+
account_created = 'account_created'
|
|
756
|
+
account_updated = 'account_updated'
|
|
757
|
+
transfer_created = 'transfer_created'
|
|
758
|
+
statement_downloaded = 'statement_downloaded'
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
class OperatorRole(str, Enum):
|
|
762
|
+
operator = 'operator'
|
|
763
|
+
authorizer = 'authorizer'
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
class OperatorStatus(str, Enum):
|
|
767
|
+
active = 'active'
|
|
768
|
+
disabled = 'disabled'
|
|
@@ -22,6 +22,7 @@ from .enums import (
|
|
|
22
22
|
CardType,
|
|
23
23
|
EventType,
|
|
24
24
|
KYCFileType,
|
|
25
|
+
OperationalEventAction,
|
|
25
26
|
SessionType,
|
|
26
27
|
TermsOfService,
|
|
27
28
|
TransferNetwork,
|
|
@@ -153,6 +154,11 @@ class AccountQuery(QueryParams):
|
|
|
153
154
|
account_number: Optional[str] = None
|
|
154
155
|
|
|
155
156
|
|
|
157
|
+
class OperationalEventQuery(QueryParams):
|
|
158
|
+
actor_id: Optional[str] = None
|
|
159
|
+
action: Optional[OperationalEventAction] = None
|
|
160
|
+
|
|
161
|
+
|
|
156
162
|
class BalanceEntryQuery(QueryParams):
|
|
157
163
|
funding_instrument_uri: Optional[str] = None
|
|
158
164
|
wallet_id: str = 'default'
|
|
@@ -18,6 +18,7 @@ from pydantic_extra_types.coordinate import Coordinate
|
|
|
18
18
|
|
|
19
19
|
from ..types.enums import (
|
|
20
20
|
AccountUseType,
|
|
21
|
+
AccountValidationStatus,
|
|
21
22
|
AuthorizerTransaction,
|
|
22
23
|
CardDesign,
|
|
23
24
|
CardFundingType,
|
|
@@ -36,6 +37,8 @@ from ..types.enums import (
|
|
|
36
37
|
KYCValidationSource,
|
|
37
38
|
MonthlyMovementsType,
|
|
38
39
|
MonthlySpendingType,
|
|
40
|
+
OperatorRole,
|
|
41
|
+
OperatorStatus,
|
|
39
42
|
PlatformType,
|
|
40
43
|
PosCapability,
|
|
41
44
|
Profession,
|
|
@@ -735,6 +738,39 @@ class LimitedWalletRequest(BaseRequest):
|
|
|
735
738
|
allowed_rfc: Optional[Rfc] = None
|
|
736
739
|
|
|
737
740
|
|
|
741
|
+
class AccountRequest(BaseRequest):
|
|
742
|
+
name: StrictStr
|
|
743
|
+
account_number: Clabe
|
|
744
|
+
alias: Optional[StrictStr] = None
|
|
745
|
+
curp: Optional[Curp] = None
|
|
746
|
+
rfc: Optional[Rfc] = None
|
|
747
|
+
|
|
748
|
+
model_config = ConfigDict(
|
|
749
|
+
json_schema_extra={
|
|
750
|
+
'example': {
|
|
751
|
+
'name': 'Aceros del Norte SA de CV',
|
|
752
|
+
'account_number': '072691004495711499',
|
|
753
|
+
'alias': 'Proveedor acero',
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
class AccountUpdateRequest(BaseRequest):
|
|
760
|
+
name: Optional[StrictStr] = None
|
|
761
|
+
alias: Optional[StrictStr] = None
|
|
762
|
+
validation_status: Optional[AccountValidationStatus] = None
|
|
763
|
+
|
|
764
|
+
model_config = ConfigDict(
|
|
765
|
+
json_schema_extra={
|
|
766
|
+
'example': {
|
|
767
|
+
'alias': 'Fletes',
|
|
768
|
+
'validation_status': 'verified',
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
|
|
738
774
|
class PlatformRequest(BaseModel):
|
|
739
775
|
name: str
|
|
740
776
|
rfc: Optional[str] = None
|
|
@@ -863,5 +899,130 @@ class PartnerUpdateRequest(BaseRequest):
|
|
|
863
899
|
shareholders: Optional[list[Shareholder]] = None
|
|
864
900
|
|
|
865
901
|
|
|
902
|
+
class MoralPersonRequest(BaseRequest):
|
|
903
|
+
legal_name: str
|
|
904
|
+
rfc: Rfc
|
|
905
|
+
legal_representatives: list[LegalRepresentative]
|
|
906
|
+
|
|
907
|
+
model_config = ConfigDict(
|
|
908
|
+
json_schema_extra={
|
|
909
|
+
'example': {
|
|
910
|
+
'legal_name': 'Aceros del Norte SA de CV',
|
|
911
|
+
'rfc': 'ADN850101ABC',
|
|
912
|
+
'legal_representatives': [
|
|
913
|
+
{
|
|
914
|
+
'names': 'Juan',
|
|
915
|
+
'first_surname': 'Perez',
|
|
916
|
+
'job': 'Director General',
|
|
917
|
+
'phone_number': '+525512345678',
|
|
918
|
+
'email_address': 'juan.perez@aceros.com',
|
|
919
|
+
'address': AddressRequest.model_json_schema().get(
|
|
920
|
+
'example'
|
|
921
|
+
),
|
|
922
|
+
}
|
|
923
|
+
],
|
|
924
|
+
}
|
|
925
|
+
},
|
|
926
|
+
)
|
|
927
|
+
|
|
928
|
+
@field_validator('rfc')
|
|
929
|
+
@classmethod
|
|
930
|
+
def validate_moral_rfc(cls, rfc: Rfc) -> Rfc:
|
|
931
|
+
if len(rfc) != 12:
|
|
932
|
+
raise ValueError('RFC must be 12 characters for moral persons')
|
|
933
|
+
return rfc
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
class MoralPersonUpdateRequest(BaseRequest):
|
|
937
|
+
legal_name: Optional[str] = None
|
|
938
|
+
rfc: Optional[Rfc] = None
|
|
939
|
+
legal_representatives: Optional[list[LegalRepresentative]] = None
|
|
940
|
+
|
|
941
|
+
@model_validator(mode="before")
|
|
942
|
+
@classmethod
|
|
943
|
+
def check_at_least_one_param(cls, values: DictStrAny) -> DictStrAny:
|
|
944
|
+
if not values:
|
|
945
|
+
raise ValueError('At least one parameter must be provided')
|
|
946
|
+
return values
|
|
947
|
+
|
|
948
|
+
@field_validator('rfc')
|
|
949
|
+
@classmethod
|
|
950
|
+
def validate_moral_rfc(cls, rfc: Optional[Rfc]) -> Optional[Rfc]:
|
|
951
|
+
if rfc is not None and len(rfc) != 12:
|
|
952
|
+
raise ValueError('RFC must be 12 characters for moral persons')
|
|
953
|
+
return rfc
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
class OperatorRequest(BaseRequest):
|
|
957
|
+
name: str
|
|
958
|
+
email: EmailStr
|
|
959
|
+
phone: PhoneNumber
|
|
960
|
+
company_user_id: str
|
|
961
|
+
role: OperatorRole
|
|
962
|
+
status: OperatorStatus = OperatorStatus.active
|
|
963
|
+
|
|
964
|
+
model_config = ConfigDict(
|
|
965
|
+
json_schema_extra={
|
|
966
|
+
'example': {
|
|
967
|
+
'name': 'Maria Lopez',
|
|
968
|
+
'email': 'maria.lopez@aceros.com',
|
|
969
|
+
'phone': '+525512345678',
|
|
970
|
+
'company_user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
|
|
971
|
+
'role': 'operator',
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
@field_validator('email', mode='before')
|
|
977
|
+
@classmethod
|
|
978
|
+
def validate_email(cls, email: str) -> str:
|
|
979
|
+
return normalize_email(email)
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
class OperatorUpdateRequest(BaseRequest):
|
|
983
|
+
name: Optional[str] = None
|
|
984
|
+
phone: Optional[PhoneNumber] = None
|
|
985
|
+
role: Optional[OperatorRole] = None
|
|
986
|
+
status: Optional[OperatorStatus] = None
|
|
987
|
+
|
|
988
|
+
@model_validator(mode="before")
|
|
989
|
+
@classmethod
|
|
990
|
+
def check_at_least_one_param(cls, values: DictStrAny) -> DictStrAny:
|
|
991
|
+
if not values:
|
|
992
|
+
raise ValueError('At least one parameter must be provided')
|
|
993
|
+
return values
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
class OperatorLoginRequest(BaseRequest):
|
|
997
|
+
email: EmailStr
|
|
998
|
+
password: Annotated[Password, LogConfig(masked=True)]
|
|
999
|
+
|
|
1000
|
+
model_config = ConfigDict(
|
|
1001
|
+
json_schema_extra={
|
|
1002
|
+
'example': {
|
|
1003
|
+
'email': 'maria.lopez@aceros.com',
|
|
1004
|
+
'password': 'supersecret',
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
@field_validator('email', mode='before')
|
|
1010
|
+
@classmethod
|
|
1011
|
+
def validate_email(cls, email: str) -> str:
|
|
1012
|
+
return normalize_email(email)
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
class OperatorLoginResponse(BaseModel):
|
|
1016
|
+
session_token: str
|
|
1017
|
+
|
|
1018
|
+
model_config = ConfigDict(
|
|
1019
|
+
json_schema_extra={
|
|
1020
|
+
'example': {
|
|
1021
|
+
'session_token': 'SEWqY5cvkISJOxHyEKjAKf8w',
|
|
1022
|
+
}
|
|
1023
|
+
},
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
|
|
866
1027
|
class PhoneVerificationAssociationRequest(BaseRequest):
|
|
867
1028
|
verification_id: str
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.1.41.dev1'
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
from pydantic_extra_types.phone_numbers import PhoneNumber
|
|
4
|
+
|
|
5
|
+
from cuenca_validations.types.enums import (
|
|
6
|
+
Country,
|
|
7
|
+
OperatorRole,
|
|
8
|
+
OperatorStatus,
|
|
9
|
+
VerificationType,
|
|
10
|
+
)
|
|
11
|
+
from cuenca_validations.types.requests import (
|
|
12
|
+
MoralPersonRequest,
|
|
13
|
+
MoralPersonUpdateRequest,
|
|
14
|
+
OperatorLoginRequest,
|
|
15
|
+
OperatorLoginResponse,
|
|
16
|
+
OperatorRequest,
|
|
17
|
+
OperatorUpdateRequest,
|
|
18
|
+
PasswordResetRequest,
|
|
19
|
+
UpdateTransferRequest,
|
|
20
|
+
UserTOSAgreementRequest,
|
|
21
|
+
UserUpdateRequest,
|
|
22
|
+
VerificationRequest,
|
|
23
|
+
)
|
|
24
|
+
from cuenca_validations.typing import DictStrAny
|
|
25
|
+
|
|
26
|
+
LEGAL_REPRESENTATIVE: DictStrAny = {
|
|
27
|
+
'names': 'Juan',
|
|
28
|
+
'first_surname': 'Perez',
|
|
29
|
+
'job': 'Director General',
|
|
30
|
+
'phone_number': '+525512345678',
|
|
31
|
+
'email_address': 'juan.perez@aceros.com',
|
|
32
|
+
'address': {
|
|
33
|
+
'street': 'Reforma',
|
|
34
|
+
'ext_number': '265',
|
|
35
|
+
'postal_code_id': 'PC2ygq9j2bS9-9tsuVawzErA',
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
MORAL_PERSON_REQUEST: DictStrAny = {
|
|
40
|
+
'legal_name': 'Aceros del Norte SA de CV',
|
|
41
|
+
'rfc': 'ADN850101ABC',
|
|
42
|
+
'legal_representatives': [LEGAL_REPRESENTATIVE],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_moral_person_request_valid() -> None:
|
|
47
|
+
req = MoralPersonRequest.model_validate(MORAL_PERSON_REQUEST)
|
|
48
|
+
assert req.legal_name == 'Aceros del Norte SA de CV'
|
|
49
|
+
assert req.rfc == 'ADN850101ABC'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_moral_person_request_rejects_physical_rfc() -> None:
|
|
53
|
+
with pytest.raises(ValidationError) as ex:
|
|
54
|
+
MoralPersonRequest.model_validate(
|
|
55
|
+
{**MORAL_PERSON_REQUEST, 'rfc': 'GOCG650418TJ1'}
|
|
56
|
+
)
|
|
57
|
+
assert 'RFC must be 12 characters for moral persons' in str(ex.value)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_moral_person_request_forbids_extra() -> None:
|
|
61
|
+
with pytest.raises(ValidationError) as ex:
|
|
62
|
+
MoralPersonRequest.model_validate(
|
|
63
|
+
{**MORAL_PERSON_REQUEST, 'foo': 'bar'}
|
|
64
|
+
)
|
|
65
|
+
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_moral_person_update_requires_at_least_one_param() -> None:
|
|
69
|
+
with pytest.raises(ValueError) as ex:
|
|
70
|
+
MoralPersonUpdateRequest()
|
|
71
|
+
assert 'At least one parameter must be provided' in str(ex.value)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_moral_person_update_valid() -> None:
|
|
75
|
+
req = MoralPersonUpdateRequest.model_validate({'legal_name': 'New name'})
|
|
76
|
+
assert req.legal_name == 'New name'
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_moral_person_update_accepts_moral_rfc() -> None:
|
|
80
|
+
req = MoralPersonUpdateRequest.model_validate({'rfc': 'ADN850101ABC'})
|
|
81
|
+
assert req.rfc == 'ADN850101ABC'
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_moral_person_update_rejects_physical_rfc() -> None:
|
|
85
|
+
with pytest.raises(ValidationError) as ex:
|
|
86
|
+
MoralPersonUpdateRequest.model_validate({'rfc': 'GOCG650418TJ1'})
|
|
87
|
+
assert 'RFC must be 12 characters for moral persons' in str(ex.value)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_operator_request_valid() -> None:
|
|
91
|
+
req = OperatorRequest(
|
|
92
|
+
name='Maria Lopez',
|
|
93
|
+
email='Maria+Tag@Aceros.com',
|
|
94
|
+
phone=PhoneNumber('+525512345678'),
|
|
95
|
+
company_user_id='USWqY5cvkISJOxHyEKjAKf8w',
|
|
96
|
+
role=OperatorRole.operator,
|
|
97
|
+
)
|
|
98
|
+
assert req.email == 'maria@aceros.com'
|
|
99
|
+
assert req.status == OperatorStatus.active
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_operator_request_rejects_invalid_role() -> None:
|
|
103
|
+
with pytest.raises(ValidationError) as ex:
|
|
104
|
+
OperatorRequest.model_validate(
|
|
105
|
+
{
|
|
106
|
+
'name': 'Maria Lopez',
|
|
107
|
+
'email': 'maria@aceros.com',
|
|
108
|
+
'phone': '+525512345678',
|
|
109
|
+
'company_user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
|
|
110
|
+
'role': 'admin',
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
assert 'role' in str(ex.value)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_operator_update_requires_at_least_one_param() -> None:
|
|
117
|
+
with pytest.raises(ValueError) as ex:
|
|
118
|
+
OperatorUpdateRequest()
|
|
119
|
+
assert 'At least one parameter must be provided' in str(ex.value)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_operator_update_valid() -> None:
|
|
123
|
+
req = OperatorUpdateRequest.model_validate({'name': 'New name'})
|
|
124
|
+
assert req.name == 'New name'
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_operator_login_request_valid() -> None:
|
|
128
|
+
req = OperatorLoginRequest.model_validate(
|
|
129
|
+
{
|
|
130
|
+
'email': 'Operator+Tag@Aceros.com',
|
|
131
|
+
'password': 'supersecret',
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
assert req.email == 'operator@aceros.com'
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_operator_login_request_rejects_short_password() -> None:
|
|
138
|
+
with pytest.raises(ValidationError) as ex:
|
|
139
|
+
OperatorLoginRequest.model_validate(
|
|
140
|
+
{
|
|
141
|
+
'email': 'operator@aceros.com',
|
|
142
|
+
'password': 'short',
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
assert 'password' in str(ex.value)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_operator_login_request_forbids_extra() -> None:
|
|
149
|
+
with pytest.raises(ValidationError) as ex:
|
|
150
|
+
OperatorLoginRequest.model_validate(
|
|
151
|
+
{
|
|
152
|
+
'email': 'operator@aceros.com',
|
|
153
|
+
'password': 'supersecret',
|
|
154
|
+
'foo': 'bar',
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_operator_login_response_valid() -> None:
|
|
161
|
+
resp = OperatorLoginResponse(session_token='SEWqY5cvkISJOxHyEKjAKf8w')
|
|
162
|
+
assert resp.session_token == 'SEWqY5cvkISJOxHyEKjAKf8w'
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@pytest.mark.parametrize('environment', ['api.stage', 'api.sandbox', 'api'])
|
|
166
|
+
def test_file_cuenca_url(environment: str) -> None:
|
|
167
|
+
request_data: DictStrAny = dict(
|
|
168
|
+
tos_id='TS67dcae8e74e81bba5a77bf47',
|
|
169
|
+
location=(19.432607, -99.133209),
|
|
170
|
+
signature_image_url=(
|
|
171
|
+
f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
utos = UserTOSAgreementRequest(**request_data)
|
|
175
|
+
assert utos.signature_image_url is not None
|
|
176
|
+
assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_file_cuenca_url_invalid() -> None:
|
|
180
|
+
request_data: DictStrAny = dict(
|
|
181
|
+
tos_id='TS67dcae8e74e81bba5a77bf47',
|
|
182
|
+
location=(19.432607, -99.133209),
|
|
183
|
+
signature_image_url=(
|
|
184
|
+
'https://cuenca.com/files/EFQL87ohvoRp-PkOTYgvQYFA/invalid'
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
with pytest.raises(ValidationError):
|
|
188
|
+
UserTOSAgreementRequest(**request_data)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_password_reset_request_serializes() -> None:
|
|
192
|
+
payload: DictStrAny = {'location': (19.432607, -99.133209)}
|
|
193
|
+
req = PasswordResetRequest.model_validate(payload)
|
|
194
|
+
assert req.model_dump() == {
|
|
195
|
+
'location': {
|
|
196
|
+
'latitude': 19.432607,
|
|
197
|
+
'longitude': -99.133209,
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_update_user_requires_at_least_one_param():
|
|
203
|
+
with pytest.raises(ValueError) as ex:
|
|
204
|
+
UserUpdateRequest()
|
|
205
|
+
assert 'At least one parameter must be provided' in str(ex.value)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_extra_params_are_not_allowed():
|
|
209
|
+
with pytest.raises(ValueError) as ex:
|
|
210
|
+
UserUpdateRequest(foo='bar')
|
|
211
|
+
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def test_update_user_update_govt() -> None:
|
|
215
|
+
govt_id: DictStrAny = {
|
|
216
|
+
"govt_id": {"type": "ine", "uri_front": "files/123"}
|
|
217
|
+
}
|
|
218
|
+
with pytest.raises(ValueError) as ex:
|
|
219
|
+
UserUpdateRequest(**govt_id)
|
|
220
|
+
assert 'uri_back must be provided for type ine' in str(ex.value)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def test_verification_request_normalizes_email() -> None:
|
|
224
|
+
req = VerificationRequest(
|
|
225
|
+
recipient='user+cuenca@Gmail.com',
|
|
226
|
+
type=VerificationType.email,
|
|
227
|
+
)
|
|
228
|
+
assert req.recipient == 'user@gmail.com'
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_verification_request_normalizes_phone() -> None:
|
|
232
|
+
req = VerificationRequest(
|
|
233
|
+
recipient='+116504401222',
|
|
234
|
+
type=VerificationType.phone,
|
|
235
|
+
)
|
|
236
|
+
assert req.recipient == '+16504401222'
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def test_user_update_request_normalizes_email() -> None:
|
|
240
|
+
req = UserUpdateRequest(email_address='user+tag@Gmail.com')
|
|
241
|
+
assert req.email_address == 'user@gmail.com'
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_user_update_request_normalizes_phone() -> None:
|
|
245
|
+
req = UserUpdateRequest(phone_number=PhoneNumber('+116504401222'))
|
|
246
|
+
assert req.phone_number == '+16504401222'
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_user_update_request_accepts_country_of_birth() -> None:
|
|
250
|
+
req = UserUpdateRequest(country_of_birth=Country.CA)
|
|
251
|
+
assert req.country_of_birth == Country.CA
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@pytest.mark.parametrize('status', ['succeeded', 'failed'])
|
|
255
|
+
def test_update_transfer_request_valid_status(status: str) -> None:
|
|
256
|
+
req = UpdateTransferRequest.model_validate({'status': status})
|
|
257
|
+
assert req.status == status
|
|
258
|
+
assert req.model_dump() == {'status': status}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@pytest.mark.parametrize('status', ['created', 'submitted', 'in_review'])
|
|
262
|
+
def test_update_transfer_request_invalid_status(status: str) -> None:
|
|
263
|
+
with pytest.raises(ValidationError) as ex:
|
|
264
|
+
UpdateTransferRequest.model_validate({'status': status})
|
|
265
|
+
assert 'status' in str(ex.value)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def test_update_transfer_request_missing_status() -> None:
|
|
269
|
+
with pytest.raises(ValidationError) as ex:
|
|
270
|
+
UpdateTransferRequest.model_validate({})
|
|
271
|
+
assert 'status' in str(ex.value)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def test_update_transfer_request_forbids_extra() -> None:
|
|
275
|
+
with pytest.raises(ValidationError) as ex:
|
|
276
|
+
UpdateTransferRequest.model_validate(
|
|
277
|
+
{'status': 'succeeded', 'foo': 'bar'}
|
|
278
|
+
)
|
|
279
|
+
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.1.40.dev1'
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from pydantic import ValidationError
|
|
3
|
-
from pydantic_extra_types.phone_numbers import PhoneNumber
|
|
4
|
-
|
|
5
|
-
from cuenca_validations.types.enums import Country, VerificationType
|
|
6
|
-
from cuenca_validations.types.requests import (
|
|
7
|
-
PasswordResetRequest,
|
|
8
|
-
UpdateTransferRequest,
|
|
9
|
-
UserTOSAgreementRequest,
|
|
10
|
-
UserUpdateRequest,
|
|
11
|
-
VerificationRequest,
|
|
12
|
-
)
|
|
13
|
-
from cuenca_validations.typing import DictStrAny
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@pytest.mark.parametrize('environment', ['api.stage', 'api.sandbox', 'api'])
|
|
17
|
-
def test_file_cuenca_url(environment: str) -> None:
|
|
18
|
-
request_data: DictStrAny = dict(
|
|
19
|
-
tos_id='TS67dcae8e74e81bba5a77bf47',
|
|
20
|
-
location=(19.432607, -99.133209),
|
|
21
|
-
signature_image_url=(
|
|
22
|
-
f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
23
|
-
),
|
|
24
|
-
)
|
|
25
|
-
utos = UserTOSAgreementRequest(**request_data)
|
|
26
|
-
assert utos.signature_image_url is not None
|
|
27
|
-
assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def test_file_cuenca_url_invalid() -> None:
|
|
31
|
-
request_data: DictStrAny = dict(
|
|
32
|
-
tos_id='TS67dcae8e74e81bba5a77bf47',
|
|
33
|
-
location=(19.432607, -99.133209),
|
|
34
|
-
signature_image_url=(
|
|
35
|
-
'https://cuenca.com/files/EFQL87ohvoRp-PkOTYgvQYFA/invalid'
|
|
36
|
-
),
|
|
37
|
-
)
|
|
38
|
-
with pytest.raises(ValidationError):
|
|
39
|
-
UserTOSAgreementRequest(**request_data)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def test_password_reset_request_serializes() -> None:
|
|
43
|
-
payload: DictStrAny = {'location': (19.432607, -99.133209)}
|
|
44
|
-
req = PasswordResetRequest.model_validate(payload)
|
|
45
|
-
assert req.model_dump() == {
|
|
46
|
-
'location': {
|
|
47
|
-
'latitude': 19.432607,
|
|
48
|
-
'longitude': -99.133209,
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def test_update_user_requires_at_least_one_param():
|
|
54
|
-
with pytest.raises(ValueError) as ex:
|
|
55
|
-
UserUpdateRequest()
|
|
56
|
-
assert 'At least one parameter must be provided' in str(ex.value)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def test_extra_params_are_not_allowed():
|
|
60
|
-
with pytest.raises(ValueError) as ex:
|
|
61
|
-
UserUpdateRequest(foo='bar')
|
|
62
|
-
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def test_update_user_update_govt() -> None:
|
|
66
|
-
govt_id: DictStrAny = {
|
|
67
|
-
"govt_id": {"type": "ine", "uri_front": "files/123"}
|
|
68
|
-
}
|
|
69
|
-
with pytest.raises(ValueError) as ex:
|
|
70
|
-
UserUpdateRequest(**govt_id)
|
|
71
|
-
assert 'uri_back must be provided for type ine' in str(ex.value)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_verification_request_normalizes_email() -> None:
|
|
75
|
-
req = VerificationRequest(
|
|
76
|
-
recipient='user+cuenca@Gmail.com',
|
|
77
|
-
type=VerificationType.email,
|
|
78
|
-
)
|
|
79
|
-
assert req.recipient == 'user@gmail.com'
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def test_verification_request_normalizes_phone() -> None:
|
|
83
|
-
req = VerificationRequest(
|
|
84
|
-
recipient='+116504401222',
|
|
85
|
-
type=VerificationType.phone,
|
|
86
|
-
)
|
|
87
|
-
assert req.recipient == '+16504401222'
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_user_update_request_normalizes_email() -> None:
|
|
91
|
-
req = UserUpdateRequest(email_address='user+tag@Gmail.com')
|
|
92
|
-
assert req.email_address == 'user@gmail.com'
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def test_user_update_request_normalizes_phone() -> None:
|
|
96
|
-
req = UserUpdateRequest(phone_number=PhoneNumber('+116504401222'))
|
|
97
|
-
assert req.phone_number == '+16504401222'
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def test_user_update_request_accepts_country_of_birth() -> None:
|
|
101
|
-
req = UserUpdateRequest(country_of_birth=Country.CA)
|
|
102
|
-
assert req.country_of_birth == Country.CA
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@pytest.mark.parametrize('status', ['succeeded', 'failed'])
|
|
106
|
-
def test_update_transfer_request_valid_status(status: str) -> None:
|
|
107
|
-
req = UpdateTransferRequest.model_validate({'status': status})
|
|
108
|
-
assert req.status == status
|
|
109
|
-
assert req.model_dump() == {'status': status}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@pytest.mark.parametrize('status', ['created', 'submitted', 'in_review'])
|
|
113
|
-
def test_update_transfer_request_invalid_status(status: str) -> None:
|
|
114
|
-
with pytest.raises(ValidationError) as ex:
|
|
115
|
-
UpdateTransferRequest.model_validate({'status': status})
|
|
116
|
-
assert 'status' in str(ex.value)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def test_update_transfer_request_missing_status() -> None:
|
|
120
|
-
with pytest.raises(ValidationError) as ex:
|
|
121
|
-
UpdateTransferRequest.model_validate({})
|
|
122
|
-
assert 'status' in str(ex.value)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def test_update_transfer_request_forbids_extra() -> None:
|
|
126
|
-
with pytest.raises(ValidationError) as ex:
|
|
127
|
-
UpdateTransferRequest.model_validate(
|
|
128
|
-
{'status': 'succeeded', 'foo': 'bar'}
|
|
129
|
-
)
|
|
130
|
-
assert 'Extra inputs are not permitted' in str(ex.value)
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/__init__.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/card_bins.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/errors.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/py.typed
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/card.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/files.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/types/morals.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/typing.py
RENAMED
|
File without changes
|
{cuenca_validations-2.1.40.dev1 → cuenca_validations-2.1.41.dev1}/cuenca_validations/validators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|