cuenca-validations 2.1.46__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.46 → cuenca_validations-2.1.47}/PKG-INFO +1 -1
  2. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/__init__.py +12 -0
  3. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/enums.py +14 -0
  4. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/queries.py +5 -0
  5. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/requests.py +87 -0
  6. cuenca_validations-2.1.47/cuenca_validations/version.py +1 -0
  7. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/PKG-INFO +1 -1
  8. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_requests.py +35 -0
  9. cuenca_validations-2.1.46/cuenca_validations/version.py +0 -1
  10. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/LICENSE +0 -0
  11. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/README.md +0 -0
  12. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/__init__.py +0 -0
  13. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/card_bins.py +0 -0
  14. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/errors.py +0 -0
  15. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/py.typed +0 -0
  16. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/card.py +0 -0
  17. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/files.py +0 -0
  18. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/general.py +0 -0
  19. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/helpers.py +0 -0
  20. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/identities.py +0 -0
  21. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/types/morals.py +0 -0
  22. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/typing.py +0 -0
  23. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations/validators.py +0 -0
  24. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/SOURCES.txt +0 -0
  25. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/dependency_links.txt +0 -0
  26. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/requires.txt +0 -0
  27. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/cuenca_validations.egg-info/top_level.txt +0 -0
  28. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/setup.cfg +0 -0
  29. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/setup.py +0 -0
  30. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/__init__.py +0 -0
  31. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_card.py +0 -0
  32. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_errors.py +0 -0
  33. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_helpers.py +0 -0
  34. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_statement.py +0 -0
  35. {cuenca_validations-2.1.46 → cuenca_validations-2.1.47}/tests/test_types.py +0 -0
  36. {cuenca_validations-2.1.46 → 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.46
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
@@ -82,6 +82,7 @@ __all__ = [
82
82
  'Profession',
83
83
  'QueryParams',
84
84
  'ReferencedClabeRequest',
85
+ 'RejectTransferOrderRequest',
85
86
  'LegalRfc',
86
87
  'Rfc',
87
88
  'QuestionnairesRequest',
@@ -106,6 +107,11 @@ __all__ = [
106
107
  'TransactionQuery',
107
108
  'TransactionStatus',
108
109
  'TransferNetwork',
110
+ 'TransferOrderLineRequest',
111
+ 'TransferOrderLineStatus',
112
+ 'TransferOrderQuery',
113
+ 'TransferOrderRequest',
114
+ 'TransferOrderStatus',
109
115
  'TransferQuery',
110
116
  'TransferRequest',
111
117
  'UpdateTransferRequest',
@@ -184,6 +190,8 @@ from .enums import (
184
190
  TrackDataMethod,
185
191
  TransactionStatus,
186
192
  TransferNetwork,
193
+ TransferOrderLineStatus,
194
+ TransferOrderStatus,
187
195
  UserCardNotification,
188
196
  UserStatus,
189
197
  UserType,
@@ -238,6 +246,7 @@ from .queries import (
238
246
  StatementQuery,
239
247
  TOSQuery,
240
248
  TransactionQuery,
249
+ TransferOrderQuery,
241
250
  TransferQuery,
242
251
  UserQuery,
243
252
  UsersTOSQuery,
@@ -271,11 +280,14 @@ from .requests import (
271
280
  PlatformRequest,
272
281
  QuestionnairesRequest,
273
282
  ReferencedClabeRequest,
283
+ RejectTransferOrderRequest,
274
284
  SavingRequest,
275
285
  SavingUpdateRequest,
276
286
  SessionRequest,
277
287
  StrictTransferRequest,
278
288
  TOSRequest,
289
+ TransferOrderLineRequest,
290
+ TransferOrderRequest,
279
291
  TransferRequest,
280
292
  UpdateTransferRequest,
281
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'
@@ -25,6 +25,7 @@ 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
@@ -233,3 +234,7 @@ class TOSQuery(QueryParams):
233
234
 
234
235
  class UsersTOSQuery(QueryParams):
235
236
  type: TermsOfService
237
+
238
+
239
+ class TransferOrderQuery(QueryParams):
240
+ status: Optional[TransferOrderStatus] = None
@@ -1009,3 +1009,90 @@ class ReferencedClabeRequest(BaseRequest):
1009
1009
 
1010
1010
  class PhoneVerificationAssociationRequest(BaseRequest):
1011
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.46
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.46'