From a71fd3e95929ca108b1ee4040f782ab48fbf6a39 Mon Sep 17 00:00:00 2001 From: Mauro de Carvalho Date: Wed, 26 Nov 2025 12:35:44 -0300 Subject: [PATCH 1/4] feat: returning errors in refund and partial refund client methods --- barte/client.py | 14 +++++++++++++ tests/test_client.py | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/barte/client.py b/barte/client.py index 0ef53aa..ae4e855 100644 --- a/barte/client.py +++ b/barte/client.py @@ -172,6 +172,13 @@ def refund_charge(self, charge_id: str, as_fraud: Optional[bool] = False) -> Cha json_response = self._request( "PATCH", f"/v2/charges/{charge_id}/refund", json={"asFraud": as_fraud} ) + + if "errors" in json_response: + error_response = from_dict( + data_class=ErrorResponse, data=json_response, config=DACITE_CONFIG + ) + error_response.raise_exception(response=json_response) + return from_dict(data_class=Charge, data=json_response, config=DACITE_CONFIG) def partial_refund_charge(self, charge_id: str, value: Decimal) -> List[Refund]: @@ -179,6 +186,13 @@ def partial_refund_charge(self, charge_id: str, value: Decimal) -> List[Refund]: json_response = self._request( "PATCH", f"/v2/charges/partial-refund/{charge_id}", json={"value": value} ) + + if isinstance(json_response, dict) and "errors" in json_response: + error_response = from_dict( + data_class=ErrorResponse, data=json_response, config=DACITE_CONFIG + ) + error_response.raise_exception(response=json_response) + return [ from_dict(data_class=PartialRefund, data=item, config=DACITE_CONFIG) for item in json_response diff --git a/tests/test_client.py b/tests/test_client.py index 1ec863a..47b0a35 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -103,6 +103,24 @@ def mock_order_unauthorized_error_response(): } +@pytest.fixture +def mock_refund_error_response(): + return { + "errors": [ + { + "code": "BAR-7010", + "title": "Refund Error", + "description": "Não foi possível realizar o reembolso", + } + ], + "metadata": { + "totalRecords": 1, + "totalPages": 1, + "requestDatetime": "2025-04-15T10:34:29.576147084-03:00[America/Sao_Paulo]", + }, + } + + @pytest.fixture def mock_charge_response(): return { @@ -704,3 +722,35 @@ def test_create_buyer_with_api_version( f"{barte_client.base_url}/v2/buyers", f"{barte_client.base_url}/v1/buyers", ] + + @patch("barte.client.requests.Session.request") + def test_refund_charge_with_error( + self, mock_request, barte_client, mock_refund_error_response + ): + """Test refund charge returns BarteError on API error""" + mock_request.return_value.json.return_value = mock_refund_error_response + mock_request.return_value.raise_for_status = Mock() + + with pytest.raises(BarteError) as exc_info: + barte_client.refund_charge("d54f6553-8bcf-4376-a995-aaffb6d29492") + + assert exc_info.value.code == "BAR-7010" + assert exc_info.value.message == "Não foi possível realizar o reembolso" + assert exc_info.value.charge_uuid is None + + @patch("barte.client.requests.Session.request") + def test_partial_refund_charge_with_error( + self, mock_request, barte_client, mock_refund_error_response + ): + """Test partial refund charge returns BarteError on API error""" + mock_request.return_value.json.return_value = mock_refund_error_response + mock_request.return_value.raise_for_status = Mock() + + with pytest.raises(BarteError) as exc_info: + barte_client.partial_refund_charge( + "d54f6553-8bcf-4376-a995-aaffb6d29492", value=10 + ) + + assert exc_info.value.code == "BAR-7010" + assert exc_info.value.message == "Não foi possível realizar o reembolso" + assert exc_info.value.charge_uuid is None From 59fcc8b8552dc93e145f65a6f31becab86ecfb6c Mon Sep 17 00:00:00 2001 From: Mauro de Carvalho Date: Wed, 26 Nov 2025 15:49:00 -0300 Subject: [PATCH 2/4] fix: adding copilot changes --- barte/client.py | 2 +- tests/test_client.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/barte/client.py b/barte/client.py index ae4e855..3f692a9 100644 --- a/barte/client.py +++ b/barte/client.py @@ -181,7 +181,7 @@ def refund_charge(self, charge_id: str, as_fraud: Optional[bool] = False) -> Cha return from_dict(data_class=Charge, data=json_response, config=DACITE_CONFIG) - def partial_refund_charge(self, charge_id: str, value: Decimal) -> List[Refund]: + def partial_refund_charge(self, charge_id: str, value: Decimal) -> List[PartialRefund]: """Refund a charge partialy""" json_response = self._request( "PATCH", f"/v2/charges/partial-refund/{charge_id}", json={"value": value} diff --git a/tests/test_client.py b/tests/test_client.py index 47b0a35..71febd5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,4 +1,5 @@ from datetime import datetime +from decimal import Decimal from unittest.mock import Mock, patch import pytest @@ -748,7 +749,7 @@ def test_partial_refund_charge_with_error( with pytest.raises(BarteError) as exc_info: barte_client.partial_refund_charge( - "d54f6553-8bcf-4376-a995-aaffb6d29492", value=10 + "d54f6553-8bcf-4376-a995-aaffb6d29492", value=Decimal("10.00") ) assert exc_info.value.code == "BAR-7010" From 8ca9174e6933ce06b16716848ffd2be10c2978e0 Mon Sep 17 00:00:00 2001 From: Mauro de Carvalho Date: Wed, 26 Nov 2025 15:58:04 -0300 Subject: [PATCH 3/4] style: fix PEP8 --- barte/client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/barte/client.py b/barte/client.py index 3f692a9..a350996 100644 --- a/barte/client.py +++ b/barte/client.py @@ -181,7 +181,9 @@ def refund_charge(self, charge_id: str, as_fraud: Optional[bool] = False) -> Cha return from_dict(data_class=Charge, data=json_response, config=DACITE_CONFIG) - def partial_refund_charge(self, charge_id: str, value: Decimal) -> List[PartialRefund]: + def partial_refund_charge( + self, charge_id: str, value: Decimal + ) -> List[PartialRefund]: """Refund a charge partialy""" json_response = self._request( "PATCH", f"/v2/charges/partial-refund/{charge_id}", json={"value": value} From 0b7c6cd336608ca9cfbd57ffc3894d8c9f43e2eb Mon Sep 17 00:00:00 2001 From: Mauro de Carvalho Date: Wed, 26 Nov 2025 16:13:47 -0300 Subject: [PATCH 4/4] fix: adding docstrings and creating test to validate additionalInfo --- barte/client.py | 12 ++++++++++-- tests/test_client.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/barte/client.py b/barte/client.py index a350996..c995898 100644 --- a/barte/client.py +++ b/barte/client.py @@ -168,7 +168,11 @@ def get_pix_qrcode(self, charge_id: str) -> PixCharge: return from_dict(data_class=PixCharge, data=json_response, config=DACITE_CONFIG) def refund_charge(self, charge_id: str, as_fraud: Optional[bool] = False) -> Charge: - """Refund a charge""" + """Refund a charge + + Raises: + BarteError: When the API returns an error response with Barte error codes. + """ json_response = self._request( "PATCH", f"/v2/charges/{charge_id}/refund", json={"asFraud": as_fraud} ) @@ -184,7 +188,11 @@ def refund_charge(self, charge_id: str, as_fraud: Optional[bool] = False) -> Cha def partial_refund_charge( self, charge_id: str, value: Decimal ) -> List[PartialRefund]: - """Refund a charge partialy""" + """Refund a charge partialy + + Raises: + BarteError: When the API returns an error response with Barte error codes. + """ json_response = self._request( "PATCH", f"/v2/charges/partial-refund/{charge_id}", json={"value": value} ) diff --git a/tests/test_client.py b/tests/test_client.py index 71febd5..a9d60a6 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -122,6 +122,25 @@ def mock_refund_error_response(): } +@pytest.fixture +def mock_refund_error_response_with_charge_uuid(): + return { + "errors": [ + { + "code": "BAR-7010", + "title": "Refund Error", + "description": "Não foi possível realizar o reembolso", + "additionalInfo": {"chargeUUID": "abc123-charge-uuid"}, + } + ], + "metadata": { + "totalRecords": 1, + "totalPages": 1, + "requestDatetime": "2025-04-15T10:34:29.576147084-03:00[America/Sao_Paulo]", + }, + } + + @pytest.fixture def mock_charge_response(): return { @@ -755,3 +774,20 @@ def test_partial_refund_charge_with_error( assert exc_info.value.code == "BAR-7010" assert exc_info.value.message == "Não foi possível realizar o reembolso" assert exc_info.value.charge_uuid is None + + @patch("barte.client.requests.Session.request") + def test_refund_charge_with_error_and_charge_uuid( + self, mock_request, barte_client, mock_refund_error_response_with_charge_uuid + ): + """Test refund charge returns BarteError with charge_uuid when provided""" + mock_request.return_value.json.return_value = ( + mock_refund_error_response_with_charge_uuid + ) + mock_request.return_value.raise_for_status = Mock() + + with pytest.raises(BarteError) as exc_info: + barte_client.refund_charge("d54f6553-8bcf-4376-a995-aaffb6d29492") + + assert exc_info.value.code == "BAR-7010" + assert exc_info.value.message == "Não foi possível realizar o reembolso" + assert exc_info.value.charge_uuid == "abc123-charge-uuid"