diff --git a/lago_python_client/invoices/clients.py b/lago_python_client/invoices/clients.py index 6746c83..4d501d5 100644 --- a/lago_python_client/invoices/clients.py +++ b/lago_python_client/invoices/clients.py @@ -7,7 +7,8 @@ UpdateCommandMixin, CreateCommandMixin, ) -from ..models.invoice import InvoiceResponse +from ..models.invoice import InvoicePreview, InvoiceResponse +from ..services.json import to_json from ..services.request import ( make_headers, make_url, @@ -131,3 +132,18 @@ def payment_url(self, resource_id: str) -> str: response_data = get_response_data(response=api_response, key="invoice_payment_details") return response_data.get("payment_url", "") if isinstance(response_data, Mapping) else "" + + def preview(self, input_object: InvoicePreview) -> InvoiceResponse: + api_response: Response = send_post_request( + url=make_url( + origin=self.base_url, + path_parts=(self.API_RESOURCE, "preview"), + ), + content=to_json(input_object.dict()), + headers=make_headers(api_key=self.api_key), + ) + + return prepare_object_response( + response_model=InvoiceResponse, + data=get_response_data(response=api_response, key=self.ROOT_NAME), + ) diff --git a/lago_python_client/models/__init__.py b/lago_python_client/models/__init__.py index ba2f4cb..e16e28f 100644 --- a/lago_python_client/models/__init__.py +++ b/lago_python_client/models/__init__.py @@ -18,7 +18,7 @@ ChargeFilters as ChargeFilters, ChargeFilter as ChargeFilter, ) -from .coupon import Coupon as Coupon, LimitationConfiguration as LimitationConfiguration +from .coupon import Coupon as Coupon, CouponsList as CouponsList, LimitationConfiguration as LimitationConfiguration from .credit import CreditResponse as CreditResponse, CreditsResponse as CreditsResponse from .credit_note import ( Item as Item, @@ -54,6 +54,7 @@ InvoiceMetadata as InvoiceMetadata, InvoiceMetadataList as InvoiceMetadataList, OneOffInvoice as OneOffInvoice, + InvoicePreview as InvoicePreview, InvoiceFeesList as InvoiceFeesList, InvoiceFee as InvoiceFee, ) diff --git a/lago_python_client/models/coupon.py b/lago_python_client/models/coupon.py index 5a2d038..5429e22 100644 --- a/lago_python_client/models/coupon.py +++ b/lago_python_client/models/coupon.py @@ -46,3 +46,7 @@ class CouponResponse(BaseResponseModel): limited_plans: Optional[bool] billable_metric_codes: Optional[List[Any]] limited_billable_metrics: Optional[bool] + + +class CouponsList(BaseModel): + __root__: List[Coupon] diff --git a/lago_python_client/models/invoice.py b/lago_python_client/models/invoice.py index 97d1796..88e4030 100644 --- a/lago_python_client/models/invoice.py +++ b/lago_python_client/models/invoice.py @@ -3,8 +3,9 @@ from lago_python_client.base_model import BaseModel from .billing_period import BillingPeriodsResponse +from .coupon import CouponsList from .credit import CreditsResponse -from .customer import CustomerResponse +from .customer import Customer, CustomerResponse from .fee import FeesResponse from .subscription import SubscriptionsResponse from .error_detail import ErrorDetailsResponse @@ -52,6 +53,14 @@ class OneOffInvoice(BaseModel): error_details: Optional[ErrorDetailsResponse] +class InvoicePreview(BaseModel): + plan_code: Optional[str] + billing_time: Optional[str] + subscription_at: Optional[str] + coupons: Optional[CouponsList] + customer: Optional[Customer] + + class InvoiceAppliedTax(BaseResponseModel): lago_id: Optional[str] lago_invoice_id: Optional[str] diff --git a/tests/test_invoice_client.py b/tests/test_invoice_client.py index e614b3e..1091bf2 100644 --- a/tests/test_invoice_client.py +++ b/tests/test_invoice_client.py @@ -6,7 +6,9 @@ from lago_python_client.client import Client from lago_python_client.exceptions import LagoApiError from lago_python_client.models import ( + Customer, Invoice, + InvoicePreview, InvoiceMetadata, InvoiceMetadataList, OneOffInvoice, @@ -29,6 +31,12 @@ def one_off_invoice_object(): return OneOffInvoice(customer_external_id="external", currency="EUR", fees=fees_list) +def invoice_preview(): + customer = Customer(name="John Doe", external_id="test1") + + return InvoicePreview(customer=customer, plan_code="test", billing_time="anniversary", subscription_at="2025-01-24") + + def mock_response(mock="invoice"): this_dir = os.path.dirname(os.path.abspath(__file__)) my_data_path = os.path.join(this_dir, "fixtures/" + mock + ".json") @@ -268,3 +276,18 @@ def test_valid_payment_url_request(httpx_mock: HTTPXMock): response = client.invoices.payment_url("5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba") assert response == "https://checkout.stripe.com/c/pay/cs_test_a1cuqFkXvH" + + +def test_valid_preview_request(httpx_mock: HTTPXMock): + client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d") + + httpx_mock.add_response( + method="POST", + url="https://api.getlago.com/api/v1/invoices/preview", + content=mock_response(), + ) + response = client.invoices.preview(invoice_preview()) + + assert response.lago_id == "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba" + assert response.status == "finalized" + assert response.payment_status == "failed"