mangopay4-python-sdk 3.57.0__tar.gz → 3.58.0__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 (97) hide show
  1. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/PKG-INFO +1 -1
  2. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/fields.py +56 -1
  3. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/resources.py +37 -3
  4. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/utils.py +56 -0
  5. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/PKG-INFO +1 -1
  6. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/SOURCES.txt +2 -1
  7. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/setup.py +1 -1
  8. mangopay4_python_sdk-3.57.0/tests/resources/settlement_sample_bad.csv → mangopay4_python_sdk-3.58.0/tests/resources/settlement_sample_bad_footer.csv +1 -1
  9. mangopay4_python_sdk-3.58.0/tests/resources/settlement_sample_bad_line.csv +8 -0
  10. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_payins.py +1 -0
  11. mangopay4_python_sdk-3.58.0/tests/test_settlements.py +159 -0
  12. mangopay4_python_sdk-3.57.0/tests/test_settlements.py +0 -60
  13. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/DESCRIPTION.md +0 -0
  14. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/LICENSE +0 -0
  15. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/MANIFEST.in +0 -0
  16. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/Makefile +0 -0
  17. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/README.md +0 -0
  18. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/__init__.py +0 -0
  19. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/api.py +0 -0
  20. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/auth.py +0 -0
  21. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/base.py +0 -0
  22. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/compat.py +0 -0
  23. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/constants.py +0 -0
  24. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/exceptions.py +0 -0
  25. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/page.py +0 -0
  26. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/query.py +0 -0
  27. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/ratelimit.py +0 -0
  28. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay/signals.py +0 -0
  29. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/dependency_links.txt +0 -0
  30. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/entry_points.txt +0 -0
  31. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/requires.txt +0 -0
  32. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/mangopay4_python_sdk.egg-info/top_level.txt +0 -0
  33. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/setup.cfg +0 -0
  34. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/__init__.py +0 -0
  35. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/card.json +0 -0
  36. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/cardregistrations.json +0 -0
  37. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/cardregistrations_update.json +0 -0
  38. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/declarative_user.json +0 -0
  39. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/legal_user.json +0 -0
  40. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/legal_user_wallet.json +0 -0
  41. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/legal_user_wallet_89.json +0 -0
  42. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/legal_user_wallet_99.json +0 -0
  43. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/list_ubo_declarations.json +0 -0
  44. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/natural_user.json +0 -0
  45. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/natural_user_wallet.json +0 -0
  46. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/natural_user_wallet_9.json +0 -0
  47. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/ubo.json +0 -0
  48. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/ubo_declaration.json +0 -0
  49. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/ubo_declaration_submit.json +0 -0
  50. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/ubo_update.json +0 -0
  51. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_list_2_per_page.json +0 -0
  52. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_list_2_per_page_page1.json +0 -0
  53. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_list_3_per_page_page2.json +0 -0
  54. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_list_full.json +0 -0
  55. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_list_page1.json +0 -0
  56. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/fixtures/user_wallet.json +0 -0
  57. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/images/image.jpg +0 -0
  58. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/mocks.py +0 -0
  59. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/resources/TestKycPageFile.png +0 -0
  60. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/resources/settlement_sample.csv +0 -0
  61. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/resources.py +0 -0
  62. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/settings.py +0 -0
  63. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_acquiring.py +0 -0
  64. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_bankaccounts.py +0 -0
  65. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_banking_aliases.py +0 -0
  66. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_base.py +0 -0
  67. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_cards.py +0 -0
  68. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_client_wallets.py +0 -0
  69. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_clients.py +0 -0
  70. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_conversion.py +0 -0
  71. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_country_authorizations.py +0 -0
  72. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_deposits.py +0 -0
  73. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_disputes.py +0 -0
  74. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_documentconsult.py +0 -0
  75. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_emoney.py +0 -0
  76. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_idempotency.py +0 -0
  77. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_identity_verification.py +0 -0
  78. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_kyc_document.py +0 -0
  79. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_kycs.py +0 -0
  80. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_mandates.py +0 -0
  81. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_notifications.py +0 -0
  82. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_payouts.py +0 -0
  83. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_preauthorizations.py +0 -0
  84. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_rate_limit.py +0 -0
  85. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_recipients.py +0 -0
  86. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_refunds.py +0 -0
  87. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_reports.py +0 -0
  88. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_reports_v2.py +0 -0
  89. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_repudiations.py +0 -0
  90. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_tokens.py +0 -0
  91. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_transactions.py +0 -0
  92. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_transfers.py +0 -0
  93. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_ubos.py +0 -0
  94. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_users.py +0 -0
  95. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_utils.py +0 -0
  96. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_virtual_account.py +0 -0
  97. {mangopay4_python_sdk-3.57.0 → mangopay4_python_sdk-3.58.0}/tests/test_wallets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mangopay4-python-sdk
3
- Version: 3.57.0
3
+ Version: 3.58.0
4
4
  Summary: A client library written in python to work with mangopay v2 api
5
5
  Home-page: https://github.com/Mangopay/mangopay2-python-sdk
6
6
  Author: Mangopay (www.mangopay.com)
@@ -15,7 +15,8 @@ from .utils import timestamp_from_datetime, timestamp_from_date, Money, DebitedB
15
15
  BusinessRecipient, RecipientPropertySchema, IndividualRecipientPropertySchema, BusinessRecipientPropertySchema, \
16
16
  CompanyNumberValidation, ReportFilter, PayInIntentExternalData, PayInIntentBuyer, SupportedBank, \
17
17
  VerificationOfPayee, PayInIntentRefund, PayInIntentCapture, PayInIntentDispute, CustomFees, MarginsResponse, \
18
- UserMargin, ConsentScope, AuthenticationResult, FlowDescriptor
18
+ UserMargin, ConsentScope, AuthenticationResult, FlowDescriptor, SettlementFooterError, SettlementLineError, \
19
+ SettlementLineErrorDetail
19
20
 
20
21
 
21
22
  class FieldDescriptor(object):
@@ -1544,4 +1545,58 @@ class FlowDescriptorField(Field):
1544
1545
  result['Beneficiaries'] = value.beneficiaries
1545
1546
  return result
1546
1547
 
1548
+ return value
1549
+
1550
+
1551
+ class SettlementFooterErrorsField(Field):
1552
+ def python_value(self, value):
1553
+ if isinstance(value, list):
1554
+ return [SettlementFooterError(footer_name=item.get('FooterName', None),
1555
+ code=item.get('Code', None),
1556
+ description=item.get('Description', None))
1557
+ if isinstance(item, dict) else item
1558
+ for item in value]
1559
+
1560
+ return value
1561
+
1562
+ def api_value(self, value):
1563
+ value = super(SettlementFooterErrorsField, self).api_value(value)
1564
+
1565
+ if isinstance(value, list):
1566
+ return [item.to_api_json() if isinstance(item, SettlementFooterError) else item
1567
+ for item in value]
1568
+
1569
+ return value
1570
+
1571
+
1572
+ class SettlementLinesErrorsField(Field):
1573
+ def python_value(self, value):
1574
+ if isinstance(value, list):
1575
+ return [self._to_line_error(item) if isinstance(item, dict) else item
1576
+ for item in value]
1577
+
1578
+ return value
1579
+
1580
+ @staticmethod
1581
+ def _to_line_error(item):
1582
+ details = item.get('Details', None)
1583
+ if isinstance(details, list):
1584
+ details = [SettlementLineErrorDetail(code=detail.get('Code', None),
1585
+ description=detail.get('Description', None))
1586
+ if isinstance(detail, dict) else detail
1587
+ for detail in details]
1588
+
1589
+ return SettlementLineError(external_provider_reference=item.get('ExternalProviderReference', None),
1590
+ external_transaction_type=item.get('ExternalTransactionType', None),
1591
+ details=details)
1592
+
1593
+ def api_value(self, value):
1594
+ value = super(SettlementLinesErrorsField, self).api_value(value)
1595
+
1596
+ if isinstance(value, list):
1597
+ return [item.to_api_json() if isinstance(item, SettlementLineError) else item
1598
+ for item in value]
1599
+
1600
+ return value
1601
+
1547
1602
  return value
@@ -22,7 +22,7 @@ from .fields import (PrimaryKeyField, EmailField, CharField,
22
22
  PayInIntentExternalDataField, PayInIntentBuyerField, SupportedBanksField, VerificationOfPayeeField,
23
23
  PayInIntentRefundField, PayInIntentCaptureField, PayInIntentDisputeField, CustomFeesField,
24
24
  UserMarginField, MarginsResponseField, ConsentScopeField, AuthenticationResultField,
25
- FlowDescriptorField)
25
+ FlowDescriptorField, SettlementFooterErrorsField, SettlementLinesErrorsField)
26
26
  from .query import InsertQuery, UpdateQuery, SelectQuery, ActionQuery, DeleteQuery
27
27
 
28
28
 
@@ -214,6 +214,13 @@ class UserConsent(BaseModel):
214
214
 
215
215
  @python_2_unicode_compatible
216
216
  class NaturalUser(User):
217
+ """
218
+ .. deprecated::
219
+ The non-SCA natural user endpoints are deprecated. Use :class:`NaturalUserSca`
220
+ (create/update via ``/sca/users/natural``) and :meth:`User.get_sca` for
221
+ retrieval instead. Kept for backward compatibility; will be removed in a
222
+ future major version.
223
+ """
217
224
  person_type = CharField(api_name='PersonType',
218
225
  choices=constants.USER_TYPE_CHOICES,
219
226
  default=constants.USER_TYPE_CHOICES.natural,
@@ -297,6 +304,13 @@ class NaturalUserSca(User):
297
304
 
298
305
  @python_2_unicode_compatible
299
306
  class LegalUser(User):
307
+ """
308
+ .. deprecated::
309
+ The non-SCA legal user endpoints are deprecated. Use :class:`LegalUserSca`
310
+ (create/update via ``/sca/users/legal``) and :meth:`User.get_sca` for
311
+ retrieval instead. Kept for backward compatibility; will be removed in a
312
+ future major version.
313
+ """
300
314
  person_type = CharField(api_name='PersonType',
301
315
  choices=constants.USER_TYPE_CHOICES,
302
316
  default=constants.USER_TYPE_CHOICES.legal,
@@ -1870,12 +1884,22 @@ class CardPreAuthorizedDepositPayIn(BaseModel):
1870
1884
  return insert.execute()
1871
1885
 
1872
1886
  def create_prior_to_complement(self, idempotency_key=None, **kwargs):
1887
+ """
1888
+ .. deprecated::
1889
+ The capture-with-complement flow is deprecated and will be removed in a
1890
+ future major version. Use :meth:`create_without_complement` instead.
1891
+ """
1873
1892
  insert = InsertQuery(self, idempotency_key, **kwargs)
1874
1893
  insert.identifier = 'CREATE_PRIOR_TO_COMPLEMENT'
1875
1894
  insert.insert_query = self.get_field_dict()
1876
1895
  return insert.execute()
1877
1896
 
1878
1897
  def create_complement(self, idempotency_key=None, **kwargs):
1898
+ """
1899
+ .. deprecated::
1900
+ The complement flow is deprecated and will be removed in a future major
1901
+ version. Use :meth:`create_without_complement` instead.
1902
+ """
1879
1903
  insert = InsertQuery(self, idempotency_key, **kwargs)
1880
1904
  insert.identifier = 'CREATE_COMPLEMENT'
1881
1905
  insert.insert_query = self.get_field_dict()
@@ -1921,12 +1945,22 @@ class PreAuthorizedDepositPayIn(BaseModel):
1921
1945
  return insert.execute()
1922
1946
 
1923
1947
  def create_prior_to_complement(self, idempotency_key=None, **kwargs):
1948
+ """
1949
+ .. deprecated::
1950
+ The capture-with-complement flow is deprecated and will be removed in a
1951
+ future major version. Use :meth:`create_without_complement` instead.
1952
+ """
1924
1953
  insert = InsertQuery(self, idempotency_key, **kwargs)
1925
1954
  insert.identifier = 'CREATE_PRIOR_TO_COMPLEMENT'
1926
1955
  insert.insert_query = self.get_field_dict()
1927
1956
  return insert.execute()
1928
1957
 
1929
1958
  def create_complement(self, idempotency_key=None, **kwargs):
1959
+ """
1960
+ .. deprecated::
1961
+ The complement flow is deprecated and will be removed in a future major
1962
+ version. Use :meth:`create_without_complement` instead.
1963
+ """
1930
1964
  insert = InsertQuery(self, idempotency_key, **kwargs)
1931
1965
  insert.identifier = 'CREATE_COMPLEMENT'
1932
1966
  insert.insert_query = self.get_field_dict()
@@ -3498,8 +3532,8 @@ class Settlement(BaseModel):
3498
3532
 
3499
3533
 
3500
3534
  class SettlementValidation(BaseModel):
3501
- footer_errors = ListField(api_name='FooterErrors')
3502
- lines_errors = ListField(api_name='LinesErrors')
3535
+ footer_errors = SettlementFooterErrorsField(api_name='FooterErrors')
3536
+ lines_errors = SettlementLinesErrorsField(api_name='LinesErrors')
3503
3537
 
3504
3538
  class Meta:
3505
3539
  verbose_name = 'settlement_validation'
@@ -1754,4 +1754,60 @@ class FlowDescriptor(object):
1754
1754
  return {
1755
1755
  "FlowId": self.flow_id,
1756
1756
  "Beneficiaries": self.beneficiaries
1757
+ }
1758
+
1759
+
1760
+ @add_camelcase_aliases
1761
+ class SettlementFooterError(object):
1762
+ def __init__(self, footer_name=None, code=None, description=None):
1763
+ self.footer_name = footer_name
1764
+ self.code = code
1765
+ self.description = description
1766
+
1767
+ def __str__(self):
1768
+ return 'SettlementFooterError: %s %s %s' % (self.footer_name, self.code, self.description)
1769
+
1770
+ def to_api_json(self):
1771
+ return {
1772
+ "FooterName": self.footer_name,
1773
+ "Code": self.code,
1774
+ "Description": self.description
1775
+ }
1776
+
1777
+
1778
+ @add_camelcase_aliases
1779
+ class SettlementLineErrorDetail(object):
1780
+ def __init__(self, code=None, description=None):
1781
+ self.code = code
1782
+ self.description = description
1783
+
1784
+ def __str__(self):
1785
+ return 'SettlementLineErrorDetail: %s %s' % (self.code, self.description)
1786
+
1787
+ def to_api_json(self):
1788
+ return {
1789
+ "Code": self.code,
1790
+ "Description": self.description
1791
+ }
1792
+
1793
+
1794
+ @add_camelcase_aliases
1795
+ class SettlementLineError(object):
1796
+ def __init__(self, external_provider_reference=None, external_transaction_type=None, details=None):
1797
+ self.external_provider_reference = external_provider_reference
1798
+ self.external_transaction_type = external_transaction_type
1799
+ self.details = details
1800
+
1801
+ def __str__(self):
1802
+ return 'SettlementLineError: %s %s' % (self.external_provider_reference, self.external_transaction_type)
1803
+
1804
+ def to_api_json(self):
1805
+ details = self.details
1806
+ if isinstance(details, list):
1807
+ details = [d.to_api_json() if isinstance(d, SettlementLineErrorDetail) else d for d in details]
1808
+
1809
+ return {
1810
+ "ExternalProviderReference": self.external_provider_reference,
1811
+ "ExternalTransactionType": self.external_transaction_type,
1812
+ "Details": details
1757
1813
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mangopay4-python-sdk
3
- Version: 3.57.0
3
+ Version: 3.58.0
4
4
  Summary: A client library written in python to work with mangopay v2 api
5
5
  Home-page: https://github.com/Mangopay/mangopay2-python-sdk
6
6
  Author: Mangopay (www.mangopay.com)
@@ -91,4 +91,5 @@ tests/fixtures/user_wallet.json
91
91
  tests/images/image.jpg
92
92
  tests/resources/TestKycPageFile.png
93
93
  tests/resources/settlement_sample.csv
94
- tests/resources/settlement_sample_bad.csv
94
+ tests/resources/settlement_sample_bad_footer.csv
95
+ tests/resources/settlement_sample_bad_line.csv
@@ -10,7 +10,7 @@ with open(path.join(here, 'DESCRIPTION.md'), encoding='utf-8') as f:
10
10
 
11
11
  setup(
12
12
  name='mangopay4-python-sdk',
13
- version='3.57.0',
13
+ version='3.58.0',
14
14
  description='A client library written in python to work with mangopay v2 api',
15
15
  long_description='This SDK is a client library for interacting with the Mangopay API.',
16
16
  url='https://github.com/Mangopay/mangopay2-python-sdk',
@@ -5,4 +5,4 @@ SettlementDate,19-06-2025,,,,,,,
5
5
  ExternalProviderName,Paypal,,,,,,,
6
6
  TotalSettlementFeesAmount,0,,,,,,,
7
7
  TotalNetSettlementAmount,99999,,,,,,,
8
- SettlementCurrency,EUR,,,,,,
8
+ SettlementCurrency,EURR,,,,,,
@@ -0,0 +1,8 @@
1
+ ExternalProviderReference,ExternalPaymentMethod,ExternalTransactionType,ExternalTransactionStatus,ExternalProcessingDate,Amount,Currency,ExternalInitialReference,ExternalProviderFees
2
+ 6TU984332A894613W,PAYPAL,PAYMENT,SETTLED,191-06-2025,1000,EUR,,0
3
+ ,,,,,,,,
4
+ SettlementDate,19-06-2025,,,,,,,
5
+ ExternalProviderName,Paypal,,,,,,,
6
+ TotalSettlementFeesAmount,0,,,,,,,
7
+ TotalNetSettlementAmount,99999,,,,,,,
8
+ SettlementCurrency,EUR,,,,,,
@@ -2519,6 +2519,7 @@ class PayInsTestLive(BaseTestLive):
2519
2519
  self.assertEqual('BANK_WIRE', created.payment_type)
2520
2520
  self.assertEqual('DIRECT', created.execution_type)
2521
2521
 
2522
+ @unittest.skip("can't be tested. API returning 500")
2522
2523
  def test_paypal_data_collection(self):
2523
2524
  data = {
2524
2525
  "sender_account_id": "A12345N343",
@@ -0,0 +1,159 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import time
4
+
5
+ import requests
6
+ import responses
7
+
8
+ from mangopay.resources import Settlement, SettlementValidation
9
+ from mangopay.utils import SettlementFooterError, SettlementLineError, SettlementLineErrorDetail
10
+ from tests import settings
11
+ from tests.test_base import BaseTest, BaseTestLive
12
+
13
+
14
+ class SettlementTestLive(BaseTestLive):
15
+ _settlement = None
16
+
17
+ def test_generate_upload_url(self):
18
+ settlement = self.create_new_settlement()
19
+ self.assertIsNotNone(settlement.settlement_id)
20
+ self.assertIsNotNone(settlement.upload_url)
21
+
22
+ def test_get_settlement(self):
23
+ settlement = self.create_new_settlement()
24
+ fetched = Settlement.get(settlement.settlement_id)
25
+ self.assertEqual('PENDING_UPLOAD', fetched.status)
26
+
27
+ def test_generate_new_upload_url(self):
28
+ settlement = self.create_new_settlement()
29
+ new_settlement = Settlement(id=settlement.settlement_id, file_name='updated_settlement_sample.csv')
30
+ result = Settlement(**new_settlement.generate_new_upload_url())
31
+ self.assertIsNotNone(result.settlement_id)
32
+ self.assertIsNotNone(result.upload_url)
33
+
34
+ def test_upload_file(self):
35
+ settlement, response = self.upload_settlement_file('settlement_sample.csv')
36
+ self.assertEqual(200, response.status_code)
37
+
38
+ def test_get_validations_footer_errors(self):
39
+ settlement, response = self.upload_settlement_file('settlement_sample_bad_footer.csv')
40
+ time.sleep(20)
41
+ validations = SettlementValidation.get(settlement.settlement_id, page=0, per_page=10)
42
+ self.assertIsNotNone(validations)
43
+ self.assertIsNotNone(validations.footer_errors)
44
+
45
+ footer_error = validations.footer_errors[0]
46
+ self.assertIsNotNone(footer_error.footer_name)
47
+ self.assertIsNotNone(footer_error.code)
48
+ self.assertIsNotNone(footer_error.description)
49
+
50
+ def test_get_validations_line_errors(self):
51
+ settlement, response = self.upload_settlement_file('settlement_sample_bad_line.csv')
52
+ time.sleep(20)
53
+ validations = SettlementValidation.get(settlement.settlement_id, page=0, per_page=10)
54
+ self.assertIsNotNone(validations)
55
+ self.assertIsNotNone(validations.lines_errors)
56
+
57
+ line_error = validations.lines_errors[0]
58
+ self.assertIsNotNone(line_error.external_provider_reference)
59
+ self.assertIsNotNone(line_error.external_transaction_type)
60
+ self.assertIsNotNone(line_error.details)
61
+
62
+ line_error_detail = line_error.details[0]
63
+ self.assertIsNotNone(line_error_detail.code)
64
+ self.assertIsNotNone(line_error_detail.description)
65
+
66
+ def test_cancel_settlement(self):
67
+ settlement, response = self.upload_settlement_file('settlement_sample_bad_line.csv')
68
+ cancelled = Settlement.cancel(settlement.settlement_id)
69
+ self.assertIsNotNone(cancelled)
70
+ self.assertEqual("CANCELLED", cancelled['status'])
71
+
72
+ @staticmethod
73
+ def create_new_settlement():
74
+ if SettlementTestLive._settlement is None:
75
+ settlement = Settlement(file_name='settlement_sample.csv')
76
+ SettlementTestLive._settlement = Settlement(**settlement.generate_upload_url())
77
+ return SettlementTestLive._settlement
78
+
79
+ def upload_settlement_file(self, file_name):
80
+ settlement = Settlement(file_name=file_name)
81
+ settlement = Settlement(**settlement.generate_upload_url())
82
+ file_path = os.path.join(os.path.dirname(__file__), 'resources', file_name)
83
+ with open(file_path, 'rb') as f:
84
+ data = f.read()
85
+
86
+ headers = {'Content-Type': 'text/csv'}
87
+ response = requests.put(settlement.upload_url, data=data, headers=headers)
88
+ return settlement, response
89
+
90
+
91
+ class SettlementValidationTest(BaseTest):
92
+ @responses.activate
93
+ def test_get_validations_dto(self):
94
+ settlement_id = "settlement_12345"
95
+ v3_url = settings.MANGOPAY_API_SANDBOX_URL.replace('v2.01', 'V3.0')
96
+ self.register_mock({
97
+ 'method': responses.GET,
98
+ 'url': v3_url + settings.MANGOPAY_CLIENT_ID +
99
+ '/payins/intents/settlements/' + settlement_id + '/validations',
100
+ 'body': {
101
+ "FooterErrors": [
102
+ {
103
+ "FooterName": "DeclaredIntentAmount",
104
+ "Code": "TOTAL_NET_MISCALCULATED",
105
+ "Description": "Declared intent amount does not match actual settlement amount"
106
+ }
107
+ ],
108
+ "LinesErrors": [
109
+ {
110
+ "ExternalProviderReference": "d3f7a1b2-4c5e-6789-abcd-ef0123456789",
111
+ "ExternalTransactionType": "REFUND",
112
+ "Details": [
113
+ {
114
+ "Code": "MATCH_REF_NOT_FOUND",
115
+ "Description": "ExternalProviderReference not found for any existing Intent in the system"
116
+ },
117
+ {
118
+ "Code": "FORMAT_DATE_INVALID",
119
+ "Description": "ExternalProcessingDate format is invalid. Expected DD-MM-YYYY"
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ },
125
+ 'status': 200
126
+ })
127
+
128
+ validations = SettlementValidation.get(settlement_id, page=1, per_page=10)
129
+
130
+ self.assertIsNotNone(validations)
131
+ self.assertIsNotNone(validations.footer_errors)
132
+ self.assertIsNotNone(validations.lines_errors)
133
+
134
+ self.assertEqual(1, len(validations.footer_errors))
135
+ footer_error = validations.footer_errors[0]
136
+ self.assertIsInstance(footer_error, SettlementFooterError)
137
+ self.assertEqual("DeclaredIntentAmount", footer_error.footer_name)
138
+ self.assertEqual("TOTAL_NET_MISCALCULATED", footer_error.code)
139
+ self.assertEqual("Declared intent amount does not match actual settlement amount",
140
+ footer_error.description)
141
+
142
+ self.assertEqual(1, len(validations.lines_errors))
143
+ line_error = validations.lines_errors[0]
144
+ self.assertIsInstance(line_error, SettlementLineError)
145
+ self.assertEqual("d3f7a1b2-4c5e-6789-abcd-ef0123456789", line_error.external_provider_reference)
146
+ self.assertEqual("REFUND", line_error.external_transaction_type)
147
+ self.assertIsNotNone(line_error.details)
148
+ self.assertEqual(2, len(line_error.details))
149
+
150
+ first_detail = line_error.details[0]
151
+ self.assertIsInstance(first_detail, SettlementLineErrorDetail)
152
+ self.assertEqual("MATCH_REF_NOT_FOUND", first_detail.code)
153
+ self.assertEqual("ExternalProviderReference not found for any existing Intent in the system",
154
+ first_detail.description)
155
+
156
+ second_detail = line_error.details[1]
157
+ self.assertEqual("FORMAT_DATE_INVALID", second_detail.code)
158
+ self.assertEqual("ExternalProcessingDate format is invalid. Expected DD-MM-YYYY",
159
+ second_detail.description)
@@ -1,60 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import os
3
- import requests
4
-
5
- from mangopay.resources import Settlement, SettlementValidation
6
- from tests.test_base import BaseTestLive
7
-
8
-
9
- class SettlementTestLive(BaseTestLive):
10
- _settlement = None
11
-
12
- def test_generate_upload_url(self):
13
- settlement = self.create_new_settlement()
14
- self.assertIsNotNone(settlement.settlement_id)
15
- self.assertIsNotNone(settlement.upload_url)
16
-
17
- def test_get_settlement(self):
18
- settlement = self.create_new_settlement()
19
- fetched = Settlement.get(settlement.settlement_id)
20
- self.assertEqual('PENDING_UPLOAD', fetched.status)
21
-
22
- def test_generate_new_upload_url(self):
23
- settlement = self.create_new_settlement()
24
- new_settlement = Settlement(id=settlement.settlement_id, file_name='updated_settlement_sample.csv')
25
- result = Settlement(**new_settlement.generate_new_upload_url())
26
- self.assertIsNotNone(result.settlement_id)
27
- self.assertIsNotNone(result.upload_url)
28
-
29
- def test_upload_file(self):
30
- settlement, response = self.upload_settlement_file('settlement_sample.csv')
31
- self.assertEqual(200, response.status_code)
32
-
33
- def test_get_validaitons(self):
34
- settlement, response = self.upload_settlement_file('settlement_sample_bad.csv')
35
- validations = SettlementValidation.get(settlement.settlement_id, page=1, per_page=10)
36
- self.assertIsNotNone(validations)
37
-
38
- def test_cancel_settlement(self):
39
- settlement, response = self.upload_settlement_file('settlement_sample_bad.csv')
40
- cancelled = Settlement.cancel(settlement.settlement_id)
41
- self.assertIsNotNone(cancelled)
42
- self.assertEqual("CANCELLED", cancelled['status'])
43
-
44
- @staticmethod
45
- def create_new_settlement():
46
- if SettlementTestLive._settlement is None:
47
- settlement = Settlement(file_name='settlement_sample.csv')
48
- SettlementTestLive._settlement = Settlement(**settlement.generate_upload_url())
49
- return SettlementTestLive._settlement
50
-
51
- def upload_settlement_file(self, file_name):
52
- settlement = Settlement(file_name=file_name)
53
- settlement = Settlement(**settlement.generate_upload_url())
54
- file_path = os.path.join(os.path.dirname(__file__), 'resources', file_name)
55
- with open(file_path, 'rb') as f:
56
- data = f.read()
57
-
58
- headers = {'Content-Type': 'text/csv'}
59
- response = requests.put(settlement.upload_url, data=data, headers=headers)
60
- return settlement, response