cuenca-validations 2.1.14.dev100__py3-none-any.whl → 2.1.14.dev101__py3-none-any.whl

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.
@@ -1,10 +1,13 @@
1
+ import datetime as dt
1
2
  import uuid
2
3
  from base64 import urlsafe_b64encode
3
- from typing import Callable, Optional
4
+ from typing import Callable, Optional, Union
4
5
 
6
+ from dateutil.relativedelta import relativedelta
5
7
  from pydantic.fields import FieldInfo
6
8
 
7
9
  from .general import LogConfig
10
+ from .identities import Curp
8
11
 
9
12
 
10
13
  def uuid_field(prefix: str = '') -> Callable[[], str]:
@@ -20,3 +23,22 @@ def get_log_config(field: FieldInfo) -> Optional[LogConfig]:
20
23
  return next(m for m in field.metadata if isinstance(m, LogConfig))
21
24
  except StopIteration:
22
25
  return None
26
+
27
+
28
+ def get_birth_date_from_curp(curp: Curp) -> dt.date:
29
+ curp_date = curp[4:10] # YYMMDD
30
+ yy = int(curp_date[:2])
31
+ current_yy = dt.date.today().year % 100
32
+ century = '19' if yy > current_yy else '20'
33
+ birth_date = dt.datetime.strptime(century + curp_date, '%Y%m%d').date()
34
+ return birth_date
35
+
36
+
37
+ def validate_age_requirement(birth_date: Union[dt.date, Curp]) -> dt.date:
38
+ if isinstance(birth_date, str):
39
+ birth_date = get_birth_date_from_curp(birth_date)
40
+
41
+ current_date = dt.date.today()
42
+ if relativedelta(current_date, birth_date).years < 18:
43
+ raise ValueError('User does not meet age requirement.')
44
+ return birth_date
@@ -51,7 +51,6 @@ from ..types.enums import (
51
51
  WebhookObject,
52
52
  )
53
53
  from ..typing import DictStrAny
54
- from ..validators import validate_age_requirement
55
54
  from .card import (
56
55
  Cvv,
57
56
  ExpMonth,
@@ -67,6 +66,7 @@ from .general import (
67
66
  SerializableIPvAnyAddress,
68
67
  StrictPositiveInt,
69
68
  )
69
+ from .helpers import validate_age_requirement
70
70
  from .identities import (
71
71
  AddressRequest,
72
72
  Beneficiary,
@@ -87,7 +87,7 @@ from .morals import (
87
87
  )
88
88
 
89
89
  CUENCA_FILE_URL = (
90
- r'^https:\/\/(?:stage|sandbox|api)\.cuenca\.com\/files\/([a-zA-Z0-9\-]+)$'
90
+ r'^https:\/\/(?:stage|sandbox|api)\.cuenca\.com\/files\/([a-zA-Z0-9\-_]+)$'
91
91
  )
92
92
 
93
93
 
@@ -330,14 +330,14 @@ class CurpValidationRequest(BaseModel):
330
330
  names: Optional[str] = None
331
331
  first_surname: Optional[str] = None
332
332
  second_surname: Optional[str] = Field(
333
- None, description='Not necessary for foreigners'
333
+ default=None, description='Not necessary for foreigners'
334
334
  )
335
335
  date_of_birth: Optional[dt.date] = None
336
336
  state_of_birth: Optional[State] = Field(
337
- None, description='In format ISO 3166 Alpha-2'
337
+ default=None, description='In format ISO 3166 Alpha-2'
338
338
  )
339
339
  country_of_birth: Optional[Country] = Field(
340
- None, description='In format ISO 3166 Alpha-2'
340
+ default=None, description='In format ISO 3166 Alpha-2'
341
341
  )
342
342
  gender: Optional[Gender] = None
343
343
  manual_curp: Optional[Curp] = Field(
@@ -376,6 +376,15 @@ class CurpValidationRequest(BaseModel):
376
376
  raise
377
377
  return date_of_birth
378
378
 
379
+ @field_validator('manual_curp')
380
+ @classmethod
381
+ def validate_manual_curp_birth_date(
382
+ cls, manual_curp: Optional[Curp]
383
+ ) -> Optional[Curp]:
384
+ if manual_curp:
385
+ validate_age_requirement(manual_curp)
386
+ return manual_curp
387
+
379
388
  @model_validator(mode="before")
380
389
  @classmethod
381
390
  def validate_state_of_birth(cls, values: DictStrAny) -> DictStrAny:
@@ -468,24 +477,12 @@ class UserRequest(BaseModel):
468
477
  @classmethod
469
478
  def validate_birth_date(cls, curp: Optional[Curp]) -> Optional[Curp]:
470
479
  if curp:
471
- current_date = dt.datetime.utcnow()
472
- curp_date = curp[4:10]
473
- century = (
474
- '19'
475
- if int(curp_date[:2]) > int(str(current_date.year)[:2])
476
- else '20'
477
- )
478
- birth_date = dt.datetime.strptime(century + curp_date, '%Y%m%d')
479
- try:
480
- validate_age_requirement(birth_date)
481
- except ValueError:
482
- raise
480
+ validate_age_requirement(curp)
483
481
  return curp
484
482
 
485
483
 
486
484
  class UserUpdateRequest(BaseModel):
487
485
  profession: Optional[Profession] = None
488
- verification_id: Optional[str] = None
489
486
  email_verification_id: Optional[str] = None
490
487
  phone_verification_id: Optional[str] = None
491
488
  address: Optional[AddressRequest] = None
@@ -493,9 +490,9 @@ class UserUpdateRequest(BaseModel):
493
490
  govt_id: Optional[KYCFile] = None
494
491
  proof_of_address: Optional[KYCFile] = None
495
492
  proof_of_life: Optional[KYCFile] = None
496
- signature: Optional[KYCFile] = None
497
493
  curp_document_uri: Optional[SerializableHttpUrl] = None
498
494
  fiscal_regime_code: Optional[SATRegimeCode] = None
495
+ pronouns: Optional[str] = None
499
496
  status: Optional[UserStatus] = None
500
497
 
501
498
  @field_validator('beneficiaries')
@@ -3,8 +3,6 @@ import datetime as dt
3
3
  from enum import Enum
4
4
  from typing import Any, Callable, Optional, Union
5
5
 
6
- from dateutil.relativedelta import relativedelta
7
-
8
6
 
9
7
  def sanitize_dict(d: dict) -> dict:
10
8
  for k, v in d.items():
@@ -42,10 +40,3 @@ def sanitize_item(
42
40
  else:
43
41
  rv = item
44
42
  return rv
45
-
46
-
47
- def validate_age_requirement(birth_date: dt.date) -> dt.date:
48
- current_date = dt.date.today()
49
- if relativedelta(current_date, birth_date).years < 18:
50
- raise ValueError('User does not meet age requirement.')
51
- return birth_date
@@ -1 +1 @@
1
- __version__ = '2.1.14.dev100'
1
+ __version__ = '2.1.14.dev101'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.14.dev100
3
+ Version: 2.1.14.dev101
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -3,27 +3,27 @@ cuenca_validations/card_bins.py,sha256=9OpK0mCrG7DlmRI8UoyXj962uFkP9J6eCbYeF-C1S
3
3
  cuenca_validations/errors.py,sha256=OtM8EgiKqYdz9Hn66AbBO96orL1or7efkyt0vh0Zxbs,1873
4
4
  cuenca_validations/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  cuenca_validations/typing.py,sha256=1QCu81IbVZZpyInjyeAuO-nF36gpT5Gi4o6V9PozuOU,204
6
- cuenca_validations/validators.py,sha256=wzwLnJ4wHggZvqp3mearbFkzvDERGeTNvJkuofQnuMc,1484
7
- cuenca_validations/version.py,sha256=OFyTzNykmZKV6GEznNQxd-RW79H6_vmpWUvMEWixSPs,30
6
+ cuenca_validations/validators.py,sha256=mYJDXxJVokl5jZIA4FYn8wkaMUnOxAH54t1Pfg_0kmQ,1190
7
+ cuenca_validations/version.py,sha256=YHLY2U93PC9BuVWJBUtjpPj6UncsMyTvSnC1DUEDeqI,30
8
8
  cuenca_validations/types/__init__.py,sha256=fPmHzU6mY6l3qK2R8cOhjcrICTOnoHS6VQteX663FRE,4843
9
9
  cuenca_validations/types/card.py,sha256=UGzz8NTFAverUmdUKAK1oGHnOnjSNTpIRUm93vKSSGY,1295
10
10
  cuenca_validations/types/enums.py,sha256=533fUCip5CXMD7m4Ww8VAcB5Yr4A0EmT5GBRt2mF4b0,19510
11
11
  cuenca_validations/types/files.py,sha256=2CszbwF9ytXV9suFFwyDjYG4XxY8UhCjRw3HttVXXNw,269
12
12
  cuenca_validations/types/general.py,sha256=vJmQBD_Iv_hsxD8x3_Bip-NlYAiE2rmXSPQKj4kTtto,2621
13
- cuenca_validations/types/helpers.py,sha256=6rHUhwoQ7jJZtGcW3LX-W5ZDl42PWE1RoBpGme7KCkk,610
13
+ cuenca_validations/types/helpers.py,sha256=XPiYVTLDtmBB5R1heWUy1c35zZMh7nh-BmS6rtwEltg,1379
14
14
  cuenca_validations/types/identities.py,sha256=1wkutHzL9Gpd9oAZdyiikNxWKe5iBVAQT3TabR6YG1o,5451
15
15
  cuenca_validations/types/morals.py,sha256=davabh5hAnFVQyM7-yCyDaT5ewXnm0cr1BtqDIwzkX8,1833
16
16
  cuenca_validations/types/queries.py,sha256=3KWQfIawcXpyfD2SxBlUJpJVkc3CXL5rNMpHU-9GZXY,4992
17
- cuenca_validations/types/requests.py,sha256=Hfpvak94BtoOn1bLQHrGK7hgE46ycCb01bhE5I9iGu8,21166
18
- cuenca_validations-2.1.14.dev100.dist-info/licenses/LICENSE,sha256=wR76FmxBbfnQpwELkkE5iMF8sFIafEMgXLTE4N4WPTc,1063
17
+ cuenca_validations/types/requests.py,sha256=U89hSAJlm8GLTlxRw7aL2jqS1aKRygRwJQpx9t_zxKo,21005
18
+ cuenca_validations-2.1.14.dev101.dist-info/licenses/LICENSE,sha256=wR76FmxBbfnQpwELkkE5iMF8sFIafEMgXLTE4N4WPTc,1063
19
19
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  tests/test_card.py,sha256=QAfRz7e11gWICPnFJZ2tiYgUsFV3C9TwzJXrDnDNXFw,1202
21
21
  tests/test_errors.py,sha256=ixiIgEuBuzfsL5p4uCFdF32XqFRtTPF6EVhGJ0keOrI,930
22
22
  tests/test_helpers.py,sha256=ubzpi1UXCryLQdgsT_Zm2IX-XE_4L0dnHnhLwH06xK8,748
23
- tests/test_requests.py,sha256=DGYWLhmJ0ryy9j1oEsFnZ9FssiClUrvZqczQGKiVVyU,1095
23
+ tests/test_requests.py,sha256=HGKybPNlN-Vbf2Ew34csfMR5UzZdVPoX9J8eeD4yCiI,1095
24
24
  tests/test_statement.py,sha256=IOE0rRRBgBZSJv_FLaETEyn5NzzXKMNTqgjv99GX-68,1436
25
- tests/test_types.py,sha256=agu5f7cbKv2SPuX8CE3Xp7K_s-MW-oLQjj86BWKcXbw,18811
26
- cuenca_validations-2.1.14.dev100.dist-info/METADATA,sha256=or7jlldsKgHLeTC8hfl2Um-fbxIrsyUhuP9S7rBb0j0,1602
27
- cuenca_validations-2.1.14.dev100.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- cuenca_validations-2.1.14.dev100.dist-info/top_level.txt,sha256=4233xdOs2HtuT-GFRjcDcwK0IwdwvWdczOtk0fPB6Gw,25
29
- cuenca_validations-2.1.14.dev100.dist-info/RECORD,,
25
+ tests/test_types.py,sha256=g7dsNxIxFT1hzBWx92JQbtMoTWBg1EQdCEwEGEFqGFk,19030
26
+ cuenca_validations-2.1.14.dev101.dist-info/METADATA,sha256=7gFtD4uDyv2aw08QrFsOYc1br2zf4yWYy9oAwtFRids,1602
27
+ cuenca_validations-2.1.14.dev101.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ cuenca_validations-2.1.14.dev101.dist-info/top_level.txt,sha256=4233xdOs2HtuT-GFRjcDcwK0IwdwvWdczOtk0fPB6Gw,25
29
+ cuenca_validations-2.1.14.dev101.dist-info/RECORD,,
tests/test_requests.py CHANGED
@@ -11,12 +11,12 @@ def test_file_cuenca_url(environment: str) -> None:
11
11
  tos_id='TS67dcae8e74e81bba5a77bf47',
12
12
  location=(19.432607, -99.133209),
13
13
  signature_image_url=(
14
- f'https://{environment}.cuenca.com/files/EFQL87ohvoRp-PkOTYgvQYFA'
14
+ f'https://{environment}.cuenca.com/files/EFQL8_ohvoRp-PkOTYgvQYFA'
15
15
  ),
16
16
  )
17
17
  utos = UserTOSAgreementRequest(**request_data)
18
18
  assert utos.signature_image_url is not None
19
- assert utos.signature_image_url.file_id == 'EFQL87ohvoRp-PkOTYgvQYFA'
19
+ assert utos.signature_image_url.file_id == 'EFQL8_ohvoRp-PkOTYgvQYFA'
20
20
 
21
21
 
22
22
  def test_file_cuenca_url_invalid() -> None:
tests/test_types.py CHANGED
@@ -385,6 +385,12 @@ def test_curp_validation_request():
385
385
  assert 'state_of_birth required' in str(v)
386
386
 
387
387
 
388
+ def test_curp_validation_request_underage() -> None:
389
+ with pytest.raises(ValueError) as v:
390
+ CurpValidationRequest(manual_curp='ABCD240614HDFSRN03')
391
+ assert 'User does not meet age requirement.' in str(v)
392
+
393
+
388
394
  def test_user_update_request():
389
395
  request = dict(
390
396
  beneficiaries=[