diff --git a/barte/client.py b/barte/client.py index 0ef53aa..c995898 100644 --- a/barte/client.py +++ b/barte/client.py @@ -168,17 +168,41 @@ 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} ) + + 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]: - """Refund a charge partialy""" + def partial_refund_charge( + self, charge_id: str, value: Decimal + ) -> List[PartialRefund]: + """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} ) + + 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..a9d60a6 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 @@ -103,6 +104,43 @@ 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_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 { @@ -704,3 +742,52 @@ 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=Decimal("10.00") + ) + + 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"