cuenca-validations 0.11.33__tar.gz → 2.0.0.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-0.11.33 → cuenca_validations-2.0.0.dev1}/PKG-INFO +4 -6
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/errors.py +5 -11
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/__init__.py +1 -3
- cuenca_validations-2.0.0.dev1/cuenca_validations/types/card.py +26 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/files.py +3 -3
- cuenca_validations-2.0.0.dev1/cuenca_validations/types/general.py +119 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/identities.py +79 -67
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/morals.py +2 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/queries.py +56 -27
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/requests.py +261 -233
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/validators.py +4 -10
- cuenca_validations-2.0.0.dev1/cuenca_validations/version.py +1 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations.egg-info/PKG-INFO +4 -6
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations.egg-info/requires.txt +2 -2
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/setup.py +3 -5
- cuenca_validations-2.0.0.dev1/tests/test_card.py +24 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/tests/test_statement.py +16 -13
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/tests/test_types.py +20 -12
- cuenca_validations-0.11.33/cuenca_validations/types/card.py +0 -53
- cuenca_validations-0.11.33/cuenca_validations/types/general.py +0 -101
- cuenca_validations-0.11.33/cuenca_validations/version.py +0 -1
- cuenca_validations-0.11.33/tests/test_card.py +0 -35
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/LICENSE +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/README.md +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/__init__.py +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/card_bins.py +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/py.typed +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/enums.py +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/typing.py +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations.egg-info/SOURCES.txt +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations.egg-info/dependency_links.txt +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations.egg-info/top_level.txt +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/setup.cfg +0 -0
- {cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/tests/__init__.py +0 -0
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cuenca_validations
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 2.0.0.dev1
|
|
4
4
|
Summary: Cuenca common validations
|
|
5
5
|
Home-page: https://github.com/cuenca-mx/cuenca-validations
|
|
6
6
|
Author: Cuenca
|
|
7
7
|
Author-email: dev@cuenca.com
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
11
9
|
Classifier: Programming Language :: Python :: 3.8
|
|
12
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
11
|
Classifier: Operating System :: OS Independent
|
|
14
|
-
Requires-Python: >=3.
|
|
12
|
+
Requires-Python: >=3.8
|
|
15
13
|
Description-Content-Type: text/markdown
|
|
16
14
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: clabe
|
|
18
|
-
Requires-Dist: pydantic[email]
|
|
15
|
+
Requires-Dist: clabe>=2.0.0
|
|
16
|
+
Requires-Dist: pydantic[email]>=2.0
|
|
19
17
|
Requires-Dist: dataclasses>=0.6; python_version < "3.7"
|
|
20
18
|
Requires-Dist: python-dateutil>=2.7.0
|
|
21
19
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'''
|
|
1
2
|
__all__ = [
|
|
2
3
|
'ApiError',
|
|
3
4
|
'AuthMethodNotAllowedError',
|
|
@@ -7,20 +8,15 @@ __all__ = [
|
|
|
7
8
|
'InvalidOTPCodeError',
|
|
8
9
|
'MissingAuthorizationHeaderError',
|
|
9
10
|
'NoPasswordFoundError',
|
|
10
|
-
'NotDigitError',
|
|
11
11
|
'TooManyAttemptsError',
|
|
12
12
|
'UserLocationError',
|
|
13
13
|
'UserNotLoggedInError',
|
|
14
14
|
'WrongCredsError',
|
|
15
15
|
]
|
|
16
16
|
|
|
17
|
-
from
|
|
18
|
-
NotDigitError as PydanticNotDigitError,
|
|
19
|
-
PydanticValueError,
|
|
20
|
-
)
|
|
17
|
+
from pydantic_core import PydanticCustomError
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
class CardBinValidationError(PydanticValueError):
|
|
19
|
+
class CardBinValidationError(PydanticCustomError):
|
|
24
20
|
code = 'payment_card_number.bin'
|
|
25
21
|
msg_template = (
|
|
26
22
|
'The card number contains a BIN (first six digits) that does not have'
|
|
@@ -30,10 +26,6 @@ class CardBinValidationError(PydanticValueError):
|
|
|
30
26
|
)
|
|
31
27
|
|
|
32
28
|
|
|
33
|
-
class NotDigitError(PydanticNotDigitError):
|
|
34
|
-
code = 'digits'
|
|
35
|
-
msg_template = 'value is not all digits'
|
|
36
|
-
|
|
37
29
|
|
|
38
30
|
class CuencaError(Exception):
|
|
39
31
|
"""Exceptions related to ApiKeys, Login, Password, etc"""
|
|
@@ -118,3 +110,5 @@ ERROR_CODES = {
|
|
|
118
110
|
InvalidOTPCodeError,
|
|
119
111
|
]
|
|
120
112
|
}
|
|
113
|
+
|
|
114
|
+
'''
|
{cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/__init__.py
RENAMED
|
@@ -52,7 +52,6 @@ __all__ = [
|
|
|
52
52
|
'PageSize',
|
|
53
53
|
'PartnerRequest',
|
|
54
54
|
'PartnerUpdateRequest',
|
|
55
|
-
'PaymentCardNumber',
|
|
56
55
|
'PhoneNumber',
|
|
57
56
|
'PlatformRequest',
|
|
58
57
|
'PlatformType',
|
|
@@ -108,7 +107,7 @@ __all__ = [
|
|
|
108
107
|
'get_state_name',
|
|
109
108
|
]
|
|
110
109
|
|
|
111
|
-
from .card import
|
|
110
|
+
from .card import StrictPaymentCardNumber
|
|
112
111
|
from .enums import (
|
|
113
112
|
AuthorizerTransaction,
|
|
114
113
|
BankAccountStatus,
|
|
@@ -182,7 +181,6 @@ from .queries import (
|
|
|
182
181
|
EventQuery,
|
|
183
182
|
FileQuery,
|
|
184
183
|
IdentityQuery,
|
|
185
|
-
PageSize,
|
|
186
184
|
QueryParams,
|
|
187
185
|
SessionQuery,
|
|
188
186
|
StatementQuery,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pydantic import BaseModel, field_validator
|
|
2
|
+
from pydantic_core import PydanticCustomError
|
|
3
|
+
from pydantic_extra_types.payment import PaymentCardBrand, PaymentCardNumber
|
|
4
|
+
|
|
5
|
+
from ..card_bins import CARD_BINS
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StrictPaymentCardNumber(BaseModel):
|
|
9
|
+
|
|
10
|
+
card_number: PaymentCardNumber
|
|
11
|
+
|
|
12
|
+
@field_validator('card_number')
|
|
13
|
+
def validate_bin(cls, card_number: PaymentCardNumber) -> PaymentCardNumber:
|
|
14
|
+
if card_number.bin not in CARD_BINS:
|
|
15
|
+
raise PydanticCustomError(
|
|
16
|
+
'payment_card_number.bin', 'Invalid BIN: Bank code not found.'
|
|
17
|
+
)
|
|
18
|
+
return card_number
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def brand(self) -> PaymentCardBrand:
|
|
22
|
+
return self.card_number.brand
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def bank_code(self) -> str:
|
|
26
|
+
return CARD_BINS[self.card_number.bin]
|
{cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/files.py
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from pydantic import
|
|
3
|
+
from pydantic import AnyHttpUrl, BaseModel
|
|
4
4
|
|
|
5
5
|
from .enums import KYCFileType
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class BatchFileMetadata(BaseModel):
|
|
9
|
-
id: Optional[str]
|
|
9
|
+
id: Optional[str] = None
|
|
10
10
|
is_back: bool
|
|
11
11
|
type: KYCFileType
|
|
12
|
-
url:
|
|
12
|
+
url: AnyHttpUrl
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Generator, Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BeforeValidator, Field
|
|
5
|
+
from typing_extensions import Annotated
|
|
6
|
+
|
|
7
|
+
from ..validators import sanitize_dict, sanitize_item
|
|
8
|
+
from .enums import State
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SantizedDict(dict):
|
|
12
|
+
def __init__(self, *args, **kwargs):
|
|
13
|
+
super().__init__(*args, **kwargs)
|
|
14
|
+
sanitize_dict(self)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class JSONEncoder(json.JSONEncoder):
|
|
18
|
+
def default(self, o):
|
|
19
|
+
return sanitize_item(o, default=super().default)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def validate_strict_positive_int(value: int) -> int:
|
|
23
|
+
if not isinstance(value, int):
|
|
24
|
+
raise ValueError("Value must be an integer")
|
|
25
|
+
if value <= 0:
|
|
26
|
+
raise ValueError("Value must be greater than 0")
|
|
27
|
+
if value > 21_474_836_47:
|
|
28
|
+
raise ValueError("Value must be less than 21_474_836_47")
|
|
29
|
+
return value
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
StrictPositiveInt = Annotated[
|
|
33
|
+
int, BeforeValidator(validate_strict_positive_int)
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_strict_positive_float(value: float) -> float:
|
|
38
|
+
if not isinstance(value, float):
|
|
39
|
+
raise ValueError("Value must be a float")
|
|
40
|
+
if value <= 0:
|
|
41
|
+
raise ValueError("Value must be greater than 0")
|
|
42
|
+
return value
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
StrictPositiveFloat = Annotated[
|
|
46
|
+
float, BeforeValidator(validate_strict_positive_float)
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Clase base para validación
|
|
51
|
+
class Digits:
|
|
52
|
+
min_length: Optional[int] = None
|
|
53
|
+
max_length: Optional[int] = None
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def __get_validators__(cls) -> Generator:
|
|
57
|
+
yield cls.validate_digits
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def validate_digits(cls, value: str) -> str:
|
|
61
|
+
if not value.isdigit():
|
|
62
|
+
raise ValueError("Value must contain only digits.")
|
|
63
|
+
if cls.min_length is not None and len(value) < cls.min_length:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
f"Value must have at least {cls.min_length} characters."
|
|
66
|
+
)
|
|
67
|
+
if cls.max_length is not None and len(value) > cls.max_length:
|
|
68
|
+
raise ValueError(
|
|
69
|
+
f"Value must have at most {cls.max_length} characters."
|
|
70
|
+
)
|
|
71
|
+
return value
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Función para crear tipos personalizados
|
|
75
|
+
def digits(min_length: Optional[int] = None, max_length: Optional[int] = None):
|
|
76
|
+
return Annotated[
|
|
77
|
+
str, Field(min_length=min_length, max_length=max_length), Digits
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
names_state = {
|
|
82
|
+
State.NE: 'Nacido en el Extranjero',
|
|
83
|
+
State.AS: 'Aguascalientes',
|
|
84
|
+
State.BC: 'Baja California',
|
|
85
|
+
State.BS: 'Baja California Sur',
|
|
86
|
+
State.CC: 'Campeche',
|
|
87
|
+
State.CS: 'Chiapas',
|
|
88
|
+
State.CH: 'Chihuahua',
|
|
89
|
+
State.CL: 'Coahuila',
|
|
90
|
+
State.CM: 'Colima',
|
|
91
|
+
State.DF: 'Ciudad de México',
|
|
92
|
+
State.DG: 'Durango',
|
|
93
|
+
State.GT: 'Guanajuato',
|
|
94
|
+
State.GR: 'Guerrero',
|
|
95
|
+
State.HG: 'Hidalgo',
|
|
96
|
+
State.JC: 'Jalisco',
|
|
97
|
+
State.MC: 'México',
|
|
98
|
+
State.MN: 'Michoacan',
|
|
99
|
+
State.MS: 'Morelos',
|
|
100
|
+
State.NT: 'Nayarit',
|
|
101
|
+
State.NL: 'Nuevo León',
|
|
102
|
+
State.OC: 'Oaxaca',
|
|
103
|
+
State.PL: 'Puebla',
|
|
104
|
+
State.QT: 'Querétaro',
|
|
105
|
+
State.QR: 'Quintana Roo',
|
|
106
|
+
State.SP: 'San Luis Potosí',
|
|
107
|
+
State.SL: 'Sinaloa',
|
|
108
|
+
State.SR: 'Sonora',
|
|
109
|
+
State.TC: 'Tabasco',
|
|
110
|
+
State.TL: 'Tlaxcala',
|
|
111
|
+
State.TS: 'Tamaulipas',
|
|
112
|
+
State.VZ: 'Veracruz',
|
|
113
|
+
State.YN: 'Yucatán',
|
|
114
|
+
State.ZS: 'Zacatecas',
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def get_state_name(state: State):
|
|
119
|
+
return names_state[state]
|
{cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/identities.py
RENAMED
|
@@ -2,8 +2,13 @@ import datetime as dt
|
|
|
2
2
|
import re
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
|
|
5
|
-
from pydantic import
|
|
6
|
-
|
|
5
|
+
from pydantic import (
|
|
6
|
+
BaseModel,
|
|
7
|
+
ConfigDict,
|
|
8
|
+
Field,
|
|
9
|
+
IPvAnyAddress,
|
|
10
|
+
model_validator,
|
|
11
|
+
)
|
|
7
12
|
from pydantic.types import StrictStr
|
|
8
13
|
|
|
9
14
|
from .enums import Country, KYCFileType, State, VerificationStatus
|
|
@@ -14,12 +19,34 @@ class PhoneNumber(StrictStr):
|
|
|
14
19
|
max_length = 15
|
|
15
20
|
regex = re.compile(r'^\+?[0-9]{10,14}$')
|
|
16
21
|
|
|
22
|
+
@classmethod
|
|
23
|
+
def __get_pydantic_core_schema__(
|
|
24
|
+
cls, source_type: Any, handler: Any
|
|
25
|
+
) -> Dict[str, Any]:
|
|
26
|
+
return {
|
|
27
|
+
'type': 'str',
|
|
28
|
+
'pattern': cls.regex.pattern,
|
|
29
|
+
'min_length': cls.min_length,
|
|
30
|
+
'max_length': cls.max_length,
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
|
|
18
34
|
class CurpField(StrictStr):
|
|
19
35
|
min_length = 18
|
|
20
36
|
max_length = 18
|
|
21
37
|
regex = re.compile(r'^[A-Z]{4}[0-9]{6}[A-Z]{6}[A-Z|0-9][0-9]$')
|
|
22
38
|
|
|
39
|
+
@classmethod
|
|
40
|
+
def __get_pydantic_core_schema__(
|
|
41
|
+
cls, source_type: Any, handler: Any
|
|
42
|
+
) -> Dict[str, Any]:
|
|
43
|
+
return {
|
|
44
|
+
'type': 'str',
|
|
45
|
+
'pattern': cls.regex.pattern,
|
|
46
|
+
'min_length': cls.min_length,
|
|
47
|
+
'max_length': cls.max_length,
|
|
48
|
+
}
|
|
49
|
+
|
|
23
50
|
|
|
24
51
|
class Rfc(StrictStr):
|
|
25
52
|
min_length = 12
|
|
@@ -42,9 +69,8 @@ class Address(BaseModel):
|
|
|
42
69
|
country: Optional[Country] = None
|
|
43
70
|
city: Optional[str] = None
|
|
44
71
|
full_name: Optional[str] = None
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
schema_extra = {
|
|
72
|
+
model_config = ConfigDict(
|
|
73
|
+
json_schema_extra={
|
|
48
74
|
"example": {
|
|
49
75
|
"street": "Reforma",
|
|
50
76
|
"ext_number": "265",
|
|
@@ -56,8 +82,10 @@ class Address(BaseModel):
|
|
|
56
82
|
"city": "Cuauhtémoc",
|
|
57
83
|
}
|
|
58
84
|
}
|
|
85
|
+
)
|
|
59
86
|
|
|
60
|
-
@
|
|
87
|
+
@model_validator(mode='before')
|
|
88
|
+
@classmethod
|
|
61
89
|
def full_name_complete(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
62
90
|
if values.get('full_name'):
|
|
63
91
|
return values
|
|
@@ -74,9 +102,8 @@ class Beneficiary(BaseModel):
|
|
|
74
102
|
phone_number: PhoneNumber
|
|
75
103
|
user_relationship: str
|
|
76
104
|
percentage: int
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
schema_extra = {
|
|
105
|
+
model_config = ConfigDict(
|
|
106
|
+
json_schema_extra={
|
|
80
107
|
"example": {
|
|
81
108
|
"name": "Juan Perez",
|
|
82
109
|
"birth_date": "1907-07-06",
|
|
@@ -85,74 +112,58 @@ class Beneficiary(BaseModel):
|
|
|
85
112
|
"percentage": 100,
|
|
86
113
|
}
|
|
87
114
|
}
|
|
115
|
+
)
|
|
88
116
|
|
|
89
117
|
|
|
90
118
|
class VerificationErrors(BaseModel):
|
|
91
|
-
identifier: str
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
'code': {
|
|
107
|
-
'description': 'Specific code of the failure in the step.'
|
|
108
|
-
},
|
|
109
|
-
'message': {'description': 'Error description'},
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
schema_extra = {
|
|
119
|
+
identifier: str = Field(
|
|
120
|
+
..., description='Unique identifier for the step validation'
|
|
121
|
+
)
|
|
122
|
+
error: str = Field(
|
|
123
|
+
...,
|
|
124
|
+
description='Error throwed on validation,'
|
|
125
|
+
' can be StepError or SystemError in case of '
|
|
126
|
+
'KYCProvider intermittence',
|
|
127
|
+
)
|
|
128
|
+
code: str = Field(
|
|
129
|
+
..., description='Specific code of the failure in the step.'
|
|
130
|
+
)
|
|
131
|
+
message: Optional[str] = Field(None, description='Error description')
|
|
132
|
+
model_config = ConfigDict(
|
|
133
|
+
json_schema_extra={
|
|
113
134
|
"example": {
|
|
114
135
|
"identifier": "age-check",
|
|
115
136
|
"error": 'StepError',
|
|
116
137
|
"code": "underage.noDOB",
|
|
117
138
|
"message": "The date of birth could not be obtained",
|
|
118
139
|
}
|
|
119
|
-
}
|
|
140
|
+
},
|
|
141
|
+
)
|
|
120
142
|
|
|
121
143
|
|
|
122
144
|
class KYCFile(BaseModel):
|
|
123
145
|
type: KYCFileType
|
|
124
|
-
uri_front: str
|
|
125
|
-
uri_back: Optional[str] =
|
|
146
|
+
uri_front: str = Field(..., description='API uri to fetch the file')
|
|
147
|
+
uri_back: Optional[str] = Field(
|
|
148
|
+
None, description='API uri to fetch the file'
|
|
149
|
+
)
|
|
126
150
|
is_mx: bool = True
|
|
127
151
|
data: Optional[dict] = None
|
|
128
|
-
status: Optional[VerificationStatus] =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
'during kyc validation'
|
|
144
|
-
},
|
|
145
|
-
'attempt': {
|
|
146
|
-
'description': 'The number of kyc_validation '
|
|
147
|
-
'intents for this docuemnt'
|
|
148
|
-
},
|
|
149
|
-
'verification_id': {
|
|
150
|
-
'description': 'The provider identifier of the '
|
|
151
|
-
'validation result'
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
schema_extra = {
|
|
152
|
+
status: Optional[VerificationStatus] = Field(
|
|
153
|
+
None, description='The status of the file depends on KYCValidation'
|
|
154
|
+
)
|
|
155
|
+
errors: Optional[List[VerificationErrors]] = Field(
|
|
156
|
+
None, description='List of document errors found during kyc validation'
|
|
157
|
+
)
|
|
158
|
+
verification_id: Optional[str] = Field(
|
|
159
|
+
None, description='The provider identifier of the validation result'
|
|
160
|
+
)
|
|
161
|
+
attempt: Optional[int] = Field(
|
|
162
|
+
None,
|
|
163
|
+
description='The number of kyc_validation intents for this document',
|
|
164
|
+
)
|
|
165
|
+
model_config = ConfigDict(
|
|
166
|
+
json_schema_extra={
|
|
156
167
|
"example": {
|
|
157
168
|
"type": "ine",
|
|
158
169
|
"is_mx": True,
|
|
@@ -162,19 +173,20 @@ class KYCFile(BaseModel):
|
|
|
162
173
|
"status": "created",
|
|
163
174
|
"errors": [],
|
|
164
175
|
}
|
|
165
|
-
}
|
|
176
|
+
},
|
|
177
|
+
)
|
|
166
178
|
|
|
167
179
|
|
|
168
180
|
class TOSAgreement(BaseModel):
|
|
169
181
|
version: str
|
|
170
182
|
ip: IPvAnyAddress
|
|
171
|
-
location: Optional[str]
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
schema_extra = {
|
|
183
|
+
location: Optional[str] = None
|
|
184
|
+
model_config = ConfigDict(
|
|
185
|
+
json_schema_extra={
|
|
175
186
|
"example": {
|
|
176
187
|
"version": "2022-01-01",
|
|
177
188
|
"ip": "192.168.0.1",
|
|
178
189
|
"location": "19.427224, -99.168082",
|
|
179
190
|
}
|
|
180
191
|
}
|
|
192
|
+
)
|
{cuenca_validations-0.11.33 → cuenca_validations-2.0.0.dev1}/cuenca_validations/types/queries.py
RENAMED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import datetime as dt
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import
|
|
5
|
-
|
|
4
|
+
from pydantic import (
|
|
5
|
+
BaseModel,
|
|
6
|
+
ConfigDict,
|
|
7
|
+
EmailStr,
|
|
8
|
+
PositiveInt,
|
|
9
|
+
conint,
|
|
10
|
+
field_validator,
|
|
11
|
+
)
|
|
6
12
|
|
|
7
13
|
from ..typing import DictStrAny
|
|
8
14
|
from ..validators import sanitize_dict
|
|
@@ -23,14 +29,11 @@ from .identities import CurpField
|
|
|
23
29
|
MAX_PAGE_SIZE = 100
|
|
24
30
|
|
|
25
31
|
|
|
26
|
-
class PageSize(ConstrainedInt):
|
|
27
|
-
gt = 0
|
|
28
|
-
le = MAX_PAGE_SIZE
|
|
29
|
-
|
|
30
|
-
|
|
31
32
|
class QueryParams(BaseModel):
|
|
32
33
|
count: bool = False
|
|
33
|
-
page_size:
|
|
34
|
+
page_size: conint( # type: ignore[valid-type]
|
|
35
|
+
gt=0, le=MAX_PAGE_SIZE
|
|
36
|
+
) = MAX_PAGE_SIZE # Add default value
|
|
34
37
|
limit: Optional[PositiveInt] = None
|
|
35
38
|
user_id: Optional[str] = None
|
|
36
39
|
created_before: Optional[dt.datetime] = None
|
|
@@ -38,9 +41,9 @@ class QueryParams(BaseModel):
|
|
|
38
41
|
related_transaction: Optional[str] = None
|
|
39
42
|
platform_id: Optional[str] = None
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
extra
|
|
43
|
-
|
|
44
|
+
model_config = ConfigDict(
|
|
45
|
+
extra="forbid",
|
|
46
|
+
json_schema_extra={
|
|
44
47
|
'count': {'description': 'Set `true` value to get only a counter'},
|
|
45
48
|
'page_size': {'description': 'Number of items per page'},
|
|
46
49
|
'limit': {'description': 'Limit of items to query'},
|
|
@@ -54,7 +57,8 @@ class QueryParams(BaseModel):
|
|
|
54
57
|
'or greater than this value, this field represents the min '
|
|
55
58
|
'creation date.'
|
|
56
59
|
},
|
|
57
|
-
}
|
|
60
|
+
},
|
|
61
|
+
)
|
|
58
62
|
|
|
59
63
|
def dict(self, *args, **kwargs) -> DictStrAny:
|
|
60
64
|
kwargs.setdefault('exclude_none', True)
|
|
@@ -93,14 +97,32 @@ class CardTransactionQuery(TransactionQuery):
|
|
|
93
97
|
class ApiKeyQuery(QueryParams):
|
|
94
98
|
active: Optional[bool] = None
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
'
|
|
100
|
-
'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
model_config = ConfigDict(
|
|
101
|
+
extra="forbid",
|
|
102
|
+
json_schema_extra={
|
|
103
|
+
'properties': {
|
|
104
|
+
'active': {
|
|
105
|
+
'description': 'Set `true` value to fetch active keys or '
|
|
106
|
+
'`false` to fetch deactivated keys'
|
|
107
|
+
},
|
|
108
|
+
'count': {
|
|
109
|
+
'description': 'Set `true` value to get only a counter'
|
|
110
|
+
},
|
|
111
|
+
'page_size': {'description': 'Number of items per page'},
|
|
112
|
+
'limit': {'description': 'Limit of items to query'},
|
|
113
|
+
'created_before': {
|
|
114
|
+
'description': 'Filtered items have a `created_at` '
|
|
115
|
+
'date equal or lower than this value, this field '
|
|
116
|
+
'represents the max creation date.'
|
|
117
|
+
},
|
|
118
|
+
'created_after': {
|
|
119
|
+
'description': 'Filtered items have a `created_at` '
|
|
120
|
+
'date equal or greater than this value, this field '
|
|
121
|
+
'represents the min creation date.'
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
)
|
|
104
126
|
|
|
105
127
|
|
|
106
128
|
class CardQuery(QueryParams):
|
|
@@ -116,10 +138,15 @@ class CardQuery(QueryParams):
|
|
|
116
138
|
status: Optional[CardStatus] = None
|
|
117
139
|
type: Optional[CardType] = None
|
|
118
140
|
|
|
119
|
-
@
|
|
120
|
-
def query_by_exp_cvv_if_number_set(cls, v,
|
|
121
|
-
if not
|
|
122
|
-
raise ValueError(
|
|
141
|
+
@field_validator('exp_month', 'exp_year', 'cvv2', 'cvv')
|
|
142
|
+
def query_by_exp_cvv_if_number_set(cls, v, info):
|
|
143
|
+
if not info.data.get('number'):
|
|
144
|
+
raise ValueError(
|
|
145
|
+
'''
|
|
146
|
+
exp_month, exp_year, cvv and cvv2 can
|
|
147
|
+
only be set when number is provided
|
|
148
|
+
'''
|
|
149
|
+
)
|
|
123
150
|
return v
|
|
124
151
|
|
|
125
152
|
|
|
@@ -127,9 +154,9 @@ class StatementQuery(QueryParams):
|
|
|
127
154
|
year: int
|
|
128
155
|
month: int
|
|
129
156
|
|
|
130
|
-
@
|
|
131
|
-
def validate_year_month(cls, month,
|
|
132
|
-
year =
|
|
157
|
+
@field_validator('month')
|
|
158
|
+
def validate_year_month(cls, month, info):
|
|
159
|
+
year = info.data['year']
|
|
133
160
|
month_now = dt.date.today().replace(day=1)
|
|
134
161
|
month_set = dt.date(year, month, 1)
|
|
135
162
|
if month_set >= month_now:
|
|
@@ -163,6 +190,8 @@ class UserQuery(QueryParams):
|
|
|
163
190
|
|
|
164
191
|
|
|
165
192
|
class IdentityQuery(QueryParams):
|
|
193
|
+
model_config = dict(arbitrary_types_allowed=True)
|
|
194
|
+
|
|
166
195
|
curp: Optional[CurpField] = None
|
|
167
196
|
rfc: Optional[str] = None
|
|
168
197
|
status: Optional[UserStatus] = None
|