Skip to content

Commit 0ef3a03

Browse files
fix: Subscription discount now supports null starts_at (#82)
1 parent d4e881a commit 0ef3a03

File tree

10 files changed

+99
-12
lines changed

10 files changed

+99
-12
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
Check our main [developer changelog](https://developer.paddle.com/?utm_source=dx&utm_medium=paddle-python-sdk) for information about changes to the Paddle Billing platform, the Paddle API, and other developer tools.
88

9+
## 1.2.2 - 2024-12-17
10+
11+
### Fixed
12+
13+
- Subscription discount now supports null `starts_at`
14+
915
## 1.2.1 - 2024-12-04
1016

1117
### Fixed

paddle_billing/Client.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def build_request_session(self) -> Session:
204204
"Authorization": f"Bearer {self.__api_key}",
205205
"Content-Type": "application/json",
206206
"Paddle-Version": str(self.use_api_version),
207-
"User-Agent": "PaddleSDK/python 1.2.1",
207+
"User-Agent": "PaddleSDK/python 1.2.2",
208208
}
209209
)
210210

paddle_billing/Entities/Subscriptions/SubscriptionDiscount.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
@dataclass
77
class SubscriptionDiscount:
88
id: str
9-
starts_at: datetime
10-
ends_at: datetime
9+
starts_at: datetime | None
10+
ends_at: datetime | None
1111

1212
@staticmethod
1313
def from_dict(data: dict) -> SubscriptionDiscount:
1414
return SubscriptionDiscount(
1515
id=data["id"],
16-
starts_at=datetime.fromisoformat(data["starts_at"]),
16+
starts_at=datetime.fromisoformat(data["starts_at"]) if data.get("starts_at") else None,
1717
ends_at=datetime.fromisoformat(data["ends_at"]) if data.get("ends_at") else None,
1818
)

paddle_billing/Notifications/Entities/Subscriptions/SubscriptionDiscount.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
@dataclass
77
class SubscriptionDiscount:
88
id: str
9-
starts_at: datetime
10-
ends_at: datetime
9+
starts_at: datetime | None
10+
ends_at: datetime | None
1111

1212
@staticmethod
1313
def from_dict(data: dict) -> SubscriptionDiscount:
1414
return SubscriptionDiscount(
1515
id=data["id"],
16-
starts_at=datetime.fromisoformat(data["starts_at"]),
16+
starts_at=datetime.fromisoformat(data["starts_at"]) if data.get("starts_at") else None,
1717
ends_at=datetime.fromisoformat(data["ends_at"]) if data.get("ends_at") else None,
1818
)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
setup(
5-
version="1.2.1",
5+
version="1.2.2",
66
author="Paddle and contributors",
77
author_email="team-dx@paddle.com",
88
description="Paddle's Python SDK for Paddle Billing",

tests/Functional/Resources/Subscriptions/_fixtures/response/list_default.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,11 @@
323323
"update_payment_method": null,
324324
"cancel": "https://sandbox-buyer-portal.paddle.com/subscriptions/sub_01hp463gxfvndqjjyqn2n7tkth/cancel"
325325
},
326-
"discount": null,
326+
"discount": {
327+
"id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
328+
"starts_at": null,
329+
"ends_at": null
330+
},
327331
"import_meta": null
328332
},
329333
{
@@ -467,7 +471,11 @@
467471
"update_payment_method": "https://buyer-portal.paddle.com/subscriptions/sub_01hn0epy6nc46wt9hw92pp2kmt/update-payment-method",
468472
"cancel": "https://buyer-portal.paddle.com/subscriptions/sub_01hn0epy6nc46wt9hw92pp2kmt/cancel"
469473
},
470-
"discount": null,
474+
"discount": {
475+
"id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
476+
"starts_at": "2024-04-12T10:18:47.635628Z",
477+
"ends_at": "2024-05-12T10:18:47.635628Z"
478+
},
471479
"import_meta": null
472480
}
473481
],

tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py

+21
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,27 @@ def test_list_subscriptions_returns_expected_response(
371371
str(expected_response_body)
372372
), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
373373

374+
def test_list_subscriptions_supports_null_discount_starts_at(
375+
self,
376+
test_client,
377+
mock_requests,
378+
):
379+
mock_requests.get(
380+
f"{test_client.base_url}/subscriptions",
381+
status_code=200,
382+
text=ReadsFixtures.read_raw_json_fixture("response/list_default"),
383+
)
384+
385+
response = test_client.client.subscriptions.list(ListSubscriptions())
386+
387+
assert isinstance(response, SubscriptionCollection)
388+
assert response.items[0].discount is None
389+
assert response.items[1].discount is None
390+
assert response.items[2].discount.starts_at is None
391+
assert response.items[2].discount.ends_at is None
392+
assert response.items[3].discount.starts_at.isoformat() == "2024-04-12T10:18:47.635628+00:00"
393+
assert response.items[3].discount.ends_at.isoformat() == "2024-05-12T10:18:47.635628+00:00"
394+
374395
@mark.parametrize(
375396
"subscription_id, includes, expected_response_status, expected_response_body, expected_url",
376397
[

tests/Unit/Entities/Notifications/test_NotificationEvent.py

+44
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,47 @@ def test_unknown_event_type_is_handled(self):
209209
assert notification_event.occurred_at.isoformat() == "2023-08-21T11:57:47.390028+00:00"
210210
assert isinstance(notification_event.data, UndefinedEntity)
211211
assert notification_event.data.to_dict()["id"] == "add_01hv8gq3318ktkfengj2r75gfx"
212+
213+
def test_subscription_notification_event_with_null_discount(self):
214+
notification_event = NotificationEvent.from_dict(
215+
{
216+
"data": loads(ReadsFixtures.read_raw_json_fixture("notification/entity/subscription.trialing")),
217+
"notification_id": "ntf_01h8bkrfe7w1vwf8xmytwn51e7",
218+
"event_type": "subscription.trialing",
219+
"event_id": "evt_01h8bzakzx3hm2fmen703n5q45",
220+
"occurred_at": "2023-08-21T11:57:47.390028Z",
221+
}
222+
)
223+
224+
assert isinstance(notification_event.data, Subscription)
225+
assert notification_event.data.discount is None
226+
227+
def test_subscription_notification_event_discount_without_starts_and_ends_at(self):
228+
notification_event = NotificationEvent.from_dict(
229+
{
230+
"data": loads(ReadsFixtures.read_raw_json_fixture("notification/entity/subscription.paused")),
231+
"notification_id": "ntf_01h8bkrfe7w1vwf8xmytwn51e7",
232+
"event_type": "subscription.paused",
233+
"event_id": "evt_01h8bzakzx3hm2fmen703n5q45",
234+
"occurred_at": "2023-08-21T11:57:47.390028Z",
235+
}
236+
)
237+
238+
assert isinstance(notification_event.data, Subscription)
239+
assert notification_event.data.discount.starts_at is None
240+
assert notification_event.data.discount.ends_at is None
241+
242+
def test_subscription_notification_event_with_discount(self):
243+
notification_event = NotificationEvent.from_dict(
244+
{
245+
"data": loads(ReadsFixtures.read_raw_json_fixture("notification/entity/subscription.created")),
246+
"notification_id": "ntf_01h8bkrfe7w1vwf8xmytwn51e7",
247+
"event_type": "subscription.created",
248+
"event_id": "evt_01h8bzakzx3hm2fmen703n5q45",
249+
"occurred_at": "2023-08-21T11:57:47.390028Z",
250+
}
251+
)
252+
253+
assert isinstance(notification_event.data, SubscriptionCreated)
254+
assert notification_event.data.discount.starts_at.isoformat() == "2024-04-12T10:18:47.635628+00:00"
255+
assert notification_event.data.discount.ends_at.isoformat() == "2024-05-12T10:18:47.635628+00:00"

tests/Unit/Entities/_fixtures/notification/entity/subscription.created.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@
117117
}
118118
],
119119
"status": "active",
120-
"discount": null,
120+
"discount": {
121+
"id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
122+
"starts_at": "2024-04-12T10:18:47.635628Z",
123+
"ends_at": "2024-05-12T10:18:47.635628Z"
124+
},
121125
"paused_at": null,
122126
"address_id": "add_01hv8gq3318ktkfengj2r75gfx",
123127
"created_at": "2024-04-12T10:18:48.831Z",

tests/Unit/Entities/_fixtures/notification/entity/subscription.paused.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@
117117
}
118118
],
119119
"status": "paused",
120-
"discount": null,
120+
"discount": {
121+
"id": "dsc_01hv6scyf7qdnzcdq01t2y8dx4",
122+
"starts_at": null,
123+
"ends_at": null
124+
},
121125
"paused_at": "2024-04-12T12:43:43.214Z",
122126
"address_id": "add_01hv8gq3318ktkfengj2r75gfx",
123127
"created_at": "2024-04-12T12:42:27.89Z",

0 commit comments

Comments
 (0)