Skip to content

Commit 59e500b

Browse files
feat: added void invoice (#318)
* feat: added void invoice * feat: added void invoice * feat: added void invoice * feat: added void invoice * feat: added void invoice
1 parent 9873c4d commit 59e500b

3 files changed

Lines changed: 231 additions & 1 deletion

File tree

lago_python_client/invoices/clients.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, Optional, Type, Mapping
1+
from typing import ClassVar, Optional, Type, Mapping, Any
22

33
from ..base_client import BaseClient
44
from ..mixins import (
@@ -161,3 +161,18 @@ def preview(self, input_object: InvoicePreview) -> InvoiceResponse:
161161
response_model=InvoiceResponse,
162162
data=get_response_data(response=api_response, key=self.ROOT_NAME),
163163
)
164+
165+
def void_invoice(self, resource_id: str, options: Mapping[str, Any] = {}) -> InvoiceResponse:
166+
api_response: Response = send_post_request(
167+
url=make_url(
168+
origin=self.base_url,
169+
path_parts=(self.API_RESOURCE, resource_id, "void"),
170+
),
171+
content=to_json(options) if options else None,
172+
headers=make_headers(api_key=self.api_key),
173+
)
174+
175+
return prepare_object_response(
176+
response_model=InvoiceResponse,
177+
data=get_response_data(response=api_response, key=self.ROOT_NAME),
178+
)

tests/fixtures/voided_invoice.json

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
{
2+
"invoice": {
3+
"lago_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
4+
"sequential_id": 15,
5+
"number": "LAG-1234-001-002",
6+
"issuing_date": "2022-06-02",
7+
"payment_due_date": "2022-06-02",
8+
"payment_overdue": false,
9+
"net_payment_term": 0,
10+
"invoice_type": "type1",
11+
"version_number": 2,
12+
"status": "voided",
13+
"payment_status": "failed",
14+
"currency": "EUR",
15+
"fees_amount_cents": 100,
16+
"taxes_amount_cents": 20,
17+
"coupons_amount_cents": 0,
18+
"credit_notes_amount_cents": 0,
19+
"progressive_billing_credit_amount_cents": 0,
20+
"sub_total_excluding_taxes_amount_cents": 100,
21+
"sub_total_including_taxes_amount_cents": 120,
22+
"prepaid_credit_amount_cents": 0,
23+
"total_amount_cents": 120,
24+
"total_due_amount_cents": 120,
25+
"metadata": [
26+
{
27+
"key": "key",
28+
"value": "value",
29+
"display_in_invoice": true
30+
}
31+
],
32+
"applied_usage_thresholds": [
33+
{
34+
"lifetime_usage_amount_cents": 120,
35+
"created_at": "2022-04-29T08:59:51Z",
36+
"usage_threshold": {
37+
"id": "7b6a2799-6db5-4f82-8362-1483b65f8f90",
38+
"threshold_display_name": "Threshold 1",
39+
"amount_cents": 100,
40+
"recurring": false
41+
}
42+
}
43+
],
44+
"applied_taxes": [
45+
{
46+
"lago_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
47+
"lago_invoice_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
48+
"lago_tax_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
49+
"tax_name": "tax name",
50+
"tax_code": "tax_code",
51+
"tax_rate": "20.0",
52+
"tax_description": "tax description",
53+
"amount_cents": 100,
54+
"amount_currency": "EUR",
55+
"fees_amount_cents": 500,
56+
"created_at": "2022-04-29T08:59:51Z"
57+
}
58+
],
59+
"customer": {
60+
"lago_id": "99a6094e-199b-4101-896a-54e927ce7bd7",
61+
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
62+
"address_line1": "5230 Penfield Ave",
63+
"address_line2": null,
64+
"city": "Woodland Hills",
65+
"country": "US",
66+
"created_at": "2022-04-29T08:59:51Z",
67+
"updated_at": "2022-04-29T08:59:51Z",
68+
"email": "dinesh@piedpiper.test",
69+
"legal_name": "Coleman-Blair",
70+
"legal_number": "49-008-2965",
71+
"logo_url": "http://hooli.com/logo.png",
72+
"name": "Gavin Belson",
73+
"phone": "1-171-883-3711 x245",
74+
"state": "CA",
75+
"url": "http://hooli.com",
76+
"zipcode": "91364",
77+
"currency": "EUR",
78+
"timezone": "Europe/Paris",
79+
"applicable_timezone": "Europe/Paris",
80+
"billing_configuration": {
81+
"payment_provider": "stripe",
82+
"payment_provider_code": "stripe-eu-1",
83+
"provider_customer_id": "cus_12345"
84+
},
85+
"taxes": [
86+
{
87+
"lago_id": "b7ab2926-1de8-4428-9bcd-779314ac129b",
88+
"name": "tax_name",
89+
"code": "tax_code",
90+
"rate": 15.0,
91+
"description": "tax_desc",
92+
"add_ons_count": 0,
93+
"customers_count": 0,
94+
"plans_count": 0,
95+
"charges_count": 0,
96+
"applied_to_organization": false,
97+
"created_at": "2022-04-29T08:59:51Z"
98+
}
99+
]
100+
},
101+
"billing_periods": [
102+
{
103+
"lago_subscription_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
104+
"external_subscription_id": "LAG-EXT-1234",
105+
"lago_plan_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
106+
"subscription_from_datetime": "2025-02-00T00:00:00Z",
107+
"subscription_to_datetime": "2025-02-28T23:59:59Z",
108+
"charges_from_datetime": "2025-01-00T00:00:00Z",
109+
"charges_to_datetime": "2025-01-31T23:59:59Z",
110+
"invoicing_reason": "subscription_periodic"
111+
}
112+
],
113+
"subscriptions": [
114+
{
115+
"lago_id": "b7ab2926-1de8-4428-9bcd-779314ac129b",
116+
"lago_customer_id": "99a6094e-199b-4101-896a-54e927ce7bd7",
117+
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
118+
"canceled_at": "2022-04-29T08:59:51Z",
119+
"created_at": "2022-04-29T08:59:51Z",
120+
"plan_code": "eartha lynch",
121+
"started_at": "2022-04-29T08:59:51Z",
122+
"status": "active",
123+
"billing_time": "anniversary",
124+
"terminated_at": null,
125+
"subscription_at": "2022-04-29T08:59:51Z",
126+
"previous_plan_code": null,
127+
"next_plan_code": null,
128+
"downgrade_plan_date": null
129+
}
130+
],
131+
"fees": [
132+
{
133+
"lago_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
134+
"lago_charge_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
135+
"invoice_display_name": "fee_invoice_display_name",
136+
"item": {
137+
"type": "charge",
138+
"code": "seats",
139+
"name": "User Seats",
140+
"invoice_display_name": "charge_invoice_display_name",
141+
"filters": {
142+
"region": ["us-east-1"]
143+
}
144+
},
145+
"amount_cents": 100,
146+
"amount_currency": "EUR",
147+
"taxes_amount_cents": 20,
148+
"taxes_rate": "20.0",
149+
"total_amount_cents": 120,
150+
"total_amount_currency": "EUR",
151+
"units": 12.6,
152+
"events_count": 4,
153+
"applied_taxes": [
154+
{
155+
"lago_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
156+
"lago_fee_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
157+
"lago_tax_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
158+
"tax_name": "tax name",
159+
"tax_code": "tax_code",
160+
"tax_rate": "20.0",
161+
"tax_description": "tax description",
162+
"amount_cents": 100,
163+
"amount_currency": "EUR",
164+
"created_at": "2022-04-29T08:59:51Z"
165+
}
166+
]
167+
}
168+
],
169+
"credits": [
170+
{
171+
"amount_cents": 20,
172+
"amount_currency": "EUR",
173+
"before_taxes": true,
174+
"item": {
175+
"type": "coupon",
176+
"code": "free_beer",
177+
"name": "Free Beer"
178+
}
179+
}
180+
]
181+
}
182+
}

tests/test_invoice_client.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,36 @@ def test_valid_preview_request(httpx_mock: HTTPXMock):
304304
assert response.lago_id == "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba"
305305
assert response.status == "finalized"
306306
assert response.payment_status == "failed"
307+
308+
309+
def test_valid_void_invoice_request_no_options(httpx_mock: HTTPXMock):
310+
client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
311+
312+
httpx_mock.add_response(
313+
method="POST",
314+
url="https://api.getlago.com/api/v1/invoices/5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba/void",
315+
content=mock_response(mock="voided_invoice"),
316+
)
317+
response = client.invoices.void_invoice("5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba")
318+
319+
assert response.lago_id == "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba"
320+
assert response.status == "voided"
321+
322+
323+
def test_valid_void_invoice_request_with_options(httpx_mock: HTTPXMock):
324+
client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
325+
326+
httpx_mock.add_response(
327+
method="POST",
328+
url="https://api.getlago.com/api/v1/invoices/5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba/void",
329+
content=mock_response(mock="voided_invoice"),
330+
)
331+
options = {
332+
"generate_credit_note": True,
333+
"refund_amount": 1000,
334+
"credit_amount": 10,
335+
}
336+
response = client.invoices.void_invoice("5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba", options)
337+
338+
assert response.lago_id == "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba"
339+
assert response.status == "voided"

0 commit comments

Comments
 (0)