cuenca-validations 2.1.45__tar.gz → 2.1.47__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.
Files changed (36) hide show
  1. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/PKG-INFO +1 -1
  2. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/__init__.py +16 -0
  3. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/enums.py +14 -0
  4. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/queries.py +11 -2
  5. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/requests.py +101 -0
  6. cuenca_validations-2.1.47/cuenca_validations/version.py +1 -0
  7. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/PKG-INFO +1 -1
  8. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_requests.py +35 -0
  9. cuenca_validations-2.1.45/cuenca_validations/version.py +0 -1
  10. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/LICENSE +0 -0
  11. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/README.md +0 -0
  12. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/__init__.py +0 -0
  13. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/card_bins.py +0 -0
  14. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/errors.py +0 -0
  15. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/py.typed +0 -0
  16. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/card.py +0 -0
  17. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/files.py +0 -0
  18. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/general.py +0 -0
  19. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/helpers.py +0 -0
  20. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/identities.py +0 -0
  21. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/types/morals.py +0 -0
  22. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/typing.py +0 -0
  23. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations/validators.py +0 -0
  24. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/SOURCES.txt +0 -0
  25. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/dependency_links.txt +0 -0
  26. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/requires.txt +0 -0
  27. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/top_level.txt +0 -0
  28. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/setup.cfg +0 -0
  29. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/setup.py +0 -0
  30. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/__init__.py +0 -0
  31. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_card.py +0 -0
  32. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_errors.py +0 -0
  33. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_helpers.py +0 -0
  34. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_statement.py +0 -0
  35. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_types.py +0 -0
  36. {cuenca_validations-2.1.45 → cuenca_validations-2.1.47}/tests/test_validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.45
3
+ Version: 2.1.47
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -46,6 +46,7 @@ __all__ = [
46
46
  'FileExtension',
47
47
  'FileFormat',
48
48
  'FileQuery',
49
+ 'ClabeQuery',
49
50
  'FileBatchUploadRequest',
50
51
  'FileRequest',
51
52
  'FileUploadRequest',
@@ -80,6 +81,8 @@ __all__ = [
80
81
  'PosCapability',
81
82
  'Profession',
82
83
  'QueryParams',
84
+ 'ReferencedClabeRequest',
85
+ 'RejectTransferOrderRequest',
83
86
  'LegalRfc',
84
87
  'Rfc',
85
88
  'QuestionnairesRequest',
@@ -104,6 +107,11 @@ __all__ = [
104
107
  'TransactionQuery',
105
108
  'TransactionStatus',
106
109
  'TransferNetwork',
110
+ 'TransferOrderLineRequest',
111
+ 'TransferOrderLineStatus',
112
+ 'TransferOrderQuery',
113
+ 'TransferOrderRequest',
114
+ 'TransferOrderStatus',
107
115
  'TransferQuery',
108
116
  'TransferRequest',
109
117
  'UpdateTransferRequest',
@@ -182,6 +190,8 @@ from .enums import (
182
190
  TrackDataMethod,
183
191
  TransactionStatus,
184
192
  TransferNetwork,
193
+ TransferOrderLineStatus,
194
+ TransferOrderStatus,
185
195
  UserCardNotification,
186
196
  UserStatus,
187
197
  UserType,
@@ -224,6 +234,7 @@ from .queries import (
224
234
  BillPaymentQuery,
225
235
  CardQuery,
226
236
  CardTransactionQuery,
237
+ ClabeQuery,
227
238
  DepositQuery,
228
239
  EventQuery,
229
240
  FileQuery,
@@ -235,6 +246,7 @@ from .queries import (
235
246
  StatementQuery,
236
247
  TOSQuery,
237
248
  TransactionQuery,
249
+ TransferOrderQuery,
238
250
  TransferQuery,
239
251
  UserQuery,
240
252
  UsersTOSQuery,
@@ -267,11 +279,15 @@ from .requests import (
267
279
  PasswordResetRequest,
268
280
  PlatformRequest,
269
281
  QuestionnairesRequest,
282
+ ReferencedClabeRequest,
283
+ RejectTransferOrderRequest,
270
284
  SavingRequest,
271
285
  SavingUpdateRequest,
272
286
  SessionRequest,
273
287
  StrictTransferRequest,
274
288
  TOSRequest,
289
+ TransferOrderLineRequest,
290
+ TransferOrderRequest,
275
291
  TransferRequest,
276
292
  UpdateTransferRequest,
277
293
  UserCredentialRequest,
@@ -761,3 +761,17 @@ class OperatorRole(str, Enum):
761
761
  class OperatorStatus(str, Enum):
762
762
  active = 'active'
763
763
  deactivated = 'deactivated'
764
+
765
+
766
+ class TransferOrderStatus(str, Enum):
767
+ created = 'created'
768
+ authorizing = 'authorizing'
769
+ authorized = 'authorized'
770
+ rejected = 'rejected'
771
+ expired = 'expired'
772
+
773
+
774
+ class TransferOrderLineStatus(str, Enum):
775
+ pending = 'pending'
776
+ invalid = 'invalid'
777
+ submitted = 'submitted'
@@ -1,5 +1,5 @@
1
1
  import datetime as dt
2
- from typing import Annotated, Optional
2
+ from typing import Annotated, Optional, Union
3
3
 
4
4
  from clabe import Clabe
5
5
  from pydantic import (
@@ -25,10 +25,11 @@ from .enums import (
25
25
  SessionType,
26
26
  TermsOfService,
27
27
  TransferNetwork,
28
+ TransferOrderStatus,
28
29
  UserStatus,
29
30
  )
30
31
  from .general import NormalizedName
31
- from .identities import Curp
32
+ from .identities import Curp, Rfc
32
33
 
33
34
  MAX_PAGE_SIZE = 100
34
35
 
@@ -206,6 +207,10 @@ class FileQuery(QueryParams):
206
207
  id: Optional[str] = None
207
208
 
208
209
 
210
+ class ClabeQuery(QueryParams):
211
+ allowed_curp_rfc: Union[Curp, Rfc]
212
+
213
+
209
214
  class BankAccountValidationQuery(QueryParams):
210
215
  account_number: Optional[str] = None
211
216
  status: Optional[BankAccountStatus] = None
@@ -229,3 +234,7 @@ class TOSQuery(QueryParams):
229
234
 
230
235
  class UsersTOSQuery(QueryParams):
231
236
  type: TermsOfService
237
+
238
+
239
+ class TransferOrderQuery(QueryParams):
240
+ status: Optional[TransferOrderStatus] = None
@@ -993,5 +993,106 @@ class OperatorLoginRequest(BaseRequest):
993
993
  return normalize_email(email)
994
994
 
995
995
 
996
+ class ReferencedClabeRequest(BaseRequest):
997
+ legal_person_id: str
998
+ allowed_curp_rfc: Union[Curp, Rfc]
999
+
1000
+ model_config = ConfigDict(
1001
+ json_schema_extra={
1002
+ 'example': {
1003
+ 'legal_person_id': 'USbIRH85qFQP5ggPKKQAu5PA',
1004
+ 'allowed_curp_rfc': 'LOPJ900101XXX',
1005
+ }
1006
+ },
1007
+ )
1008
+
1009
+
996
1010
  class PhoneVerificationAssociationRequest(BaseRequest):
997
1011
  verification_id: str
1012
+
1013
+
1014
+ MAX_TRANSFER_ORDER_BATCH_LINES = 5000
1015
+ MAX_TRANSFER_ORDER_EXPIRATION_HOURS = 24 * 7
1016
+
1017
+
1018
+ class TransferOrderLineRequest(BaseRequest):
1019
+ account_number: str
1020
+ recipient_name: str
1021
+ amount: int
1022
+ descriptor: str
1023
+
1024
+ model_config = ConfigDict(
1025
+ json_schema_extra={
1026
+ 'example': {
1027
+ 'account_number': '646180157034181180',
1028
+ 'recipient_name': 'Doroteo Arango',
1029
+ 'amount': 100_00,
1030
+ 'descriptor': 'Mezcal, pulque y tequila',
1031
+ }
1032
+ },
1033
+ )
1034
+
1035
+
1036
+ class TransferOrderRequest(BaseRequest):
1037
+ account_number: Optional[str] = None
1038
+ recipient_name: Optional[str] = None
1039
+ amount: Optional[int] = None
1040
+ descriptor: Optional[str] = None
1041
+ idempotency_key: str
1042
+ user_id: Optional[str] = None
1043
+ items: Optional[list[TransferOrderLineRequest]] = None
1044
+ expires_in_hours: Optional[int] = Field(
1045
+ default=None,
1046
+ gt=0,
1047
+ le=MAX_TRANSFER_ORDER_EXPIRATION_HOURS,
1048
+ )
1049
+
1050
+ model_config = ConfigDict(
1051
+ json_schema_extra={
1052
+ 'example': {
1053
+ 'account_number': '646180157034181180',
1054
+ 'recipient_name': 'Doroteo Arango',
1055
+ 'amount': 100_00,
1056
+ 'descriptor': 'Mezcal, pulque y tequila',
1057
+ 'idempotency_key': 'UNIQUE-KEY-003',
1058
+ 'user_id': 'USWqY5cvkISJOxHyEKjAKf8w',
1059
+ }
1060
+ },
1061
+ )
1062
+
1063
+ @model_validator(mode='after')
1064
+ def require_unitario_or_batch(self) -> 'TransferOrderRequest':
1065
+ has_items = bool(self.items)
1066
+ has_flat = all(
1067
+ (
1068
+ self.account_number is not None,
1069
+ self.recipient_name is not None,
1070
+ self.amount is not None,
1071
+ self.descriptor is not None,
1072
+ )
1073
+ )
1074
+ if has_items == has_flat:
1075
+ raise ValueError(
1076
+ 'Provide either a single transfer (account_number, '
1077
+ 'recipient_name, amount, descriptor) or items[] for a batch, '
1078
+ 'not both'
1079
+ )
1080
+ if self.items is not None:
1081
+ if len(self.items) > MAX_TRANSFER_ORDER_BATCH_LINES:
1082
+ raise ValueError(
1083
+ 'Batch exceeds maximum of '
1084
+ f'{MAX_TRANSFER_ORDER_BATCH_LINES} lines'
1085
+ )
1086
+ if len(self.items) == 0:
1087
+ raise ValueError('items must not be empty')
1088
+ return self
1089
+
1090
+
1091
+ class RejectTransferOrderRequest(BaseRequest):
1092
+ rejection_reason: str
1093
+
1094
+ model_config = ConfigDict(
1095
+ json_schema_extra={
1096
+ 'example': {'rejection_reason': 'Monto incorrecto'},
1097
+ },
1098
+ )
@@ -0,0 +1 @@
1
+ __version__ = '2.1.47'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuenca_validations
3
- Version: 2.1.45
3
+ Version: 2.1.47
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -9,10 +9,12 @@ from cuenca_validations.types.enums import (
9
9
  )
10
10
  from cuenca_validations.types.queries import OperatorQuery
11
11
  from cuenca_validations.types.requests import (
12
+ MAX_TRANSFER_ORDER_BATCH_LINES,
12
13
  OperatorLoginRequest,
13
14
  OperatorRequest,
14
15
  OperatorUpdateRequest,
15
16
  PasswordResetRequest,
17
+ TransferOrderRequest,
16
18
  UpdateTransferRequest,
17
19
  UserTOSAgreementRequest,
18
20
  UserUpdateRequest,
@@ -218,3 +220,36 @@ def test_update_transfer_request_forbids_extra() -> None:
218
220
  {'status': 'succeeded', 'foo': 'bar'}
219
221
  )
220
222
  assert 'Extra inputs are not permitted' in str(ex.value)
223
+
224
+
225
+ def test_transfer_order_request_shape() -> None:
226
+ line = {
227
+ 'account_number': '646180157034181180',
228
+ 'recipient_name': 'Doroteo Arango',
229
+ 'amount': 100_00,
230
+ 'descriptor': 'Mezcal',
231
+ }
232
+ single = TransferOrderRequest.model_validate(
233
+ {**line, 'idempotency_key': 'single'}
234
+ )
235
+ assert single.items is None
236
+ batch = TransferOrderRequest.model_validate(
237
+ {'idempotency_key': 'batch', 'items': [line]}
238
+ )
239
+ assert batch.items is not None
240
+
241
+ with pytest.raises(ValidationError, match='not both'):
242
+ TransferOrderRequest.model_validate(
243
+ {**line, 'idempotency_key': 'both', 'items': [line]}
244
+ )
245
+ with pytest.raises(ValidationError, match='items must not be empty'):
246
+ TransferOrderRequest.model_validate(
247
+ {**line, 'idempotency_key': 'empty', 'items': []}
248
+ )
249
+ with pytest.raises(ValidationError, match='Batch exceeds maximum'):
250
+ TransferOrderRequest.model_validate(
251
+ {
252
+ 'idempotency_key': 'too-many',
253
+ 'items': [line] * (MAX_TRANSFER_ORDER_BATCH_LINES + 1),
254
+ }
255
+ )
@@ -1 +0,0 @@
1
- __version__ = '2.1.45'