diff --git a/fintoc/core.py b/fintoc/core.py index f16a5bf..92c443f 100644 --- a/fintoc/core.py +++ b/fintoc/core.py @@ -11,6 +11,7 @@ InvoicesManager, LinksManager, PaymentIntentsManager, + PaymentLinksManager, RefreshIntentsManager, RefundsManager, SubscriptionIntentsManager, @@ -50,6 +51,7 @@ def __init__(self, api_key, api_version=None, jws_private_key=None): self.payment_intents = PaymentIntentsManager( "/v1/payment_intents", self._client ) + self.payment_links = PaymentLinksManager("/v1/payment_links", self._client) self.refunds = RefundsManager("/v1/refunds", self._client) self.subscriptions = SubscriptionsManager("/v1/subscriptions", self._client) self.subscription_intents = SubscriptionIntentsManager( diff --git a/fintoc/managers/__init__.py b/fintoc/managers/__init__.py index 94357d8..6d5d663 100644 --- a/fintoc/managers/__init__.py +++ b/fintoc/managers/__init__.py @@ -7,6 +7,7 @@ from .links_manager import LinksManager from .movements_manager import MovementsManager from .payment_intents_manager import PaymentIntentsManager +from .payment_links_manager import PaymentLinksManager from .refresh_intents_manager import RefreshIntentsManager from .refunds_manager import RefundsManager from .subscription_intents_manager import SubscriptionIntentsManager diff --git a/fintoc/managers/payment_intents_manager.py b/fintoc/managers/payment_intents_manager.py index 797c42d..7980246 100644 --- a/fintoc/managers/payment_intents_manager.py +++ b/fintoc/managers/payment_intents_manager.py @@ -8,9 +8,14 @@ class PaymentIntentsManager(ManagerMixin): """Represents a payment_intents manager.""" resource = "payment_intent" - methods = ["list", "get", "create", "expire"] + methods = ["list", "get", "create", "expire", "check_eligibility"] def _expire(self, identifier, **kwargs): """Expire a payment intent.""" path = f"{self._build_path(**kwargs)}/{identifier}/expire" return self._create(path_=path, **kwargs) + + def _check_eligibility(self, **kwargs): + """Check eligibility for a payment intent.""" + path = f"{self._build_path(**kwargs)}/check_eligibility" + return self._create(path_=path, **kwargs) diff --git a/fintoc/managers/payment_links_manager.py b/fintoc/managers/payment_links_manager.py new file mode 100644 index 0000000..0399984 --- /dev/null +++ b/fintoc/managers/payment_links_manager.py @@ -0,0 +1,16 @@ +"""Module to hold the payment_links manager.""" + +from fintoc.mixins import ManagerMixin + + +class PaymentLinksManager(ManagerMixin): + + """Represents a payment_links manager.""" + + resource = "payment_link" + methods = ["list", "get", "create", "cancel"] + + def _cancel(self, identifier, **kwargs): + """Cancel a payment link.""" + path = f"{self._build_path(**kwargs)}/{identifier}/cancel" + return self._update(identifier, path_=path, **kwargs) diff --git a/fintoc/mixins/manager_mixin.py b/fintoc/mixins/manager_mixin.py index 55a4215..1d7b076 100644 --- a/fintoc/mixins/manager_mixin.py +++ b/fintoc/mixins/manager_mixin.py @@ -118,13 +118,14 @@ def _create(self, idempotency_key=None, path_=None, **kwargs): return self.post_create_handler(object_, **kwargs) @can_raise_fintoc_error - def _update(self, identifier, **kwargs): + def _update(self, identifier, path_=None, **kwargs): """ Update an instance of the resource being handled by the manager, identified by :identifier:. Data is passed using :kwargs:, as specified by the API. """ klass = get_resource_class(self.__class__.resource) + custom_path = path_ if path_ else None object_ = resource_update( client=self._client, path=self._build_path(**kwargs), @@ -133,6 +134,7 @@ def _update(self, identifier, **kwargs): handlers=self._handlers, methods=self.__class__.methods, params=kwargs, + custom_path=custom_path, ) return self.post_update_handler(object_, identifier, **kwargs) diff --git a/fintoc/mixins/resource_mixin.py b/fintoc/mixins/resource_mixin.py index 58e600f..08d6ad3 100644 --- a/fintoc/mixins/resource_mixin.py +++ b/fintoc/mixins/resource_mixin.py @@ -61,8 +61,10 @@ def serialize(self): return serialized @can_raise_fintoc_error - def _update(self, **kwargs): + def _update(self, path_=None, **kwargs): + """Update the resource.""" id_ = getattr(self, self.__class__.resource_identifier) + custom_path = path_ if path_ else None object_ = resource_update( client=self._client, path=self._path, @@ -71,6 +73,7 @@ def _update(self, **kwargs): handlers=self._handlers, methods=self._methods, params=kwargs, + custom_path=custom_path, ) object_ = self._handlers.get("update")(object_, id_, **kwargs) self.__dict__.update(object_.__dict__) diff --git a/fintoc/resource_handlers.py b/fintoc/resource_handlers.py index 1a892ed..1fa92df 100644 --- a/fintoc/resource_handlers.py +++ b/fintoc/resource_handlers.py @@ -59,9 +59,12 @@ def resource_create( ) -def resource_update(client, path, id_, klass, handlers, methods, params): +def resource_update( + client, path, id_, klass, handlers, methods, params, custom_path=None +): """Update a specific instance of a resource.""" - data = client.request(f"{path}/{id_}", method="patch", json=params) + update_path = custom_path if custom_path else f"{path}/{id_}" + data = client.request(update_path, method="patch", json=params) return objetize( klass, client, diff --git a/fintoc/resources/__init__.py b/fintoc/resources/__init__.py index 1074e61..a5e7cad 100644 --- a/fintoc/resources/__init__.py +++ b/fintoc/resources/__init__.py @@ -14,6 +14,7 @@ from .movement import Movement from .other_taxes import OtherTaxes from .payment_intent import PaymentIntent +from .payment_link import PaymentLink from .refresh_intent import RefreshIntent from .services_invoice import ServicesInvoice from .subscription import Subscription diff --git a/fintoc/resources/payment_link.py b/fintoc/resources/payment_link.py new file mode 100644 index 0000000..f44de40 --- /dev/null +++ b/fintoc/resources/payment_link.py @@ -0,0 +1,7 @@ +"""Module to hold the PaymentLink resource.""" + +from fintoc.mixins import ResourceMixin + + +class PaymentLink(ResourceMixin): + """Represents a Fintoc PaymentLink.""" diff --git a/fintoc/version.py b/fintoc/version.py index c61a2b5..28e764b 100644 --- a/fintoc/version.py +++ b/fintoc/version.py @@ -1,4 +1,4 @@ """Module to hold the version utilities.""" -version_info = (2, 13, 0) +version_info = (2, 14, 0) __version__ = ".".join([str(x) for x in version_info]) diff --git a/pyproject.toml b/pyproject.toml index ad29e8c..671be82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "fintoc" -version = "2.13.0" +version = "2.14.0" description = "The official Python client for the Fintoc API." authors = ["Daniel Leal ", "Nebil Kawas "] maintainers = ["Daniel Leal "] diff --git a/tests/mixins/test_manager_mixin.py b/tests/mixins/test_manager_mixin.py index f09b2c9..e55b320 100644 --- a/tests/mixins/test_manager_mixin.py +++ b/tests/mixins/test_manager_mixin.py @@ -154,6 +154,12 @@ def test_update_method(self): assert isinstance(object_, ResourceMixin) assert object_.method == "patch" + def test_update_update_method_with_custom_path(self): + object_ = self.manager.update("my_id", path_="/resources/my_id/cancel") + assert isinstance(object_, ResourceMixin) + assert object_.method == "patch" + assert object_.url == "resources/my_id/cancel" + def test_delete_method(self): id_ = self.manager.delete("my_id") isinstance(id_, str) diff --git a/tests/mixins/test_resource_mixin.py b/tests/mixins/test_resource_mixin.py index d0bd99d..dc8f1f4 100644 --- a/tests/mixins/test_resource_mixin.py +++ b/tests/mixins/test_resource_mixin.py @@ -267,3 +267,20 @@ def test_empty_mock_resource_update_method(self, capsys): assert data["id"] not in resource.url assert data["identifier"] in resource.url + + def test_resource_update_with_custom_path(self, capsys): + methods = ["update"] + data = { + "id": "id0", + "identifier": "identifier0", + } + resource = EmptyMockResource( + self.client, self.handlers, methods, self.path, **data + ) + + custom_path = f"{self.path}/id0/cancel" + resource.update(path_=custom_path) + + captured = capsys.readouterr().out + assert "update" in captured + assert resource.url == custom_path.lstrip("/") diff --git a/tests/test_integration.py b/tests/test_integration.py index a4805a1..0ea03cc 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -392,6 +392,61 @@ def test_payment_intent_expire(self): assert result.method == "post" assert result.url == f"v1/payment_intents/{payment_intent_id}/expire" + def test_payment_intent_check_eligibility(self): + """Test checking eligibility for a payment intent.""" + eligibility_data = { + "amount": 1000, + "currency": "CLP", + } + + result = self.fintoc.payment_intents.check_eligibility(**eligibility_data) + + assert result.method == "post" + assert result.url == "v1/payment_intents/check_eligibility" + + def test_payment_links_list(self): + """Test getting all payment links.""" + payment_links = list(self.fintoc.payment_links.list()) + + assert len(payment_links) > 0 + for payment_link in payment_links: + assert payment_link.method == "get" + assert payment_link.url == "v1/payment_links" + + def test_payment_link_get(self): + """Test getting a specific payment link.""" + payment_link_id = "test_payment_link_id" + + payment_link = self.fintoc.payment_links.get(payment_link_id) + + assert payment_link.method == "get" + assert payment_link.url == f"v1/payment_links/{payment_link_id}" + + def test_payment_link_create(self): + """Test creating a payment link.""" + payment_link_data = { + "amount": 1000, + "currency": "CLP", + "description": "Test payment link", + } + + payment_link = self.fintoc.payment_links.create(**payment_link_data) + + assert payment_link.method == "post" + assert payment_link.url == "v1/payment_links" + assert payment_link.json.amount == payment_link_data["amount"] + assert payment_link.json.currency == payment_link_data["currency"] + assert payment_link.json.description == payment_link_data["description"] + + def test_payment_link_cancel(self): + """Test canceling a payment link.""" + payment_link_id = "test_payment_link_id" + + result = self.fintoc.payment_links.cancel(payment_link_id) + + assert result.method == "patch" + assert result.url == f"v1/payment_links/{payment_link_id}/cancel" + def test_refund_list(self): """Test getting all refunds.""" refunds = list(self.fintoc.refunds.list())