From c2ba603c22b6193186c6c882ca18f6ef33d28271 Mon Sep 17 00:00:00 2001 From: davidgrayston-paddle Date: Thu, 19 Dec 2024 09:43:17 +0000 Subject: [PATCH] feat: Add on_resume support to subscription resume and pause operations (#86) --- CHANGELOG.md | 6 +++ paddle_billing/Client.py | 2 +- .../Subscriptions/SubscriptionOnResume.py | 6 +++ .../Entities/Subscriptions/__init__.py | 1 + .../Operations/PauseSubscription.py | 4 +- .../Operations/ResumeSubscription.py | 4 +- setup.py | 2 +- .../pause_resume_existing_billing_period.json | 5 ++ .../pause_resume_new_billing_period.json | 5 ++ .../resume_existing_billing_period.json | 4 ++ .../request/resume_new_billing_period.json | 4 ++ .../Subscriptions/test_SubscriptionsClient.py | 49 +++++++++++++++++++ 12 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 paddle_billing/Entities/Subscriptions/SubscriptionOnResume.py create mode 100644 tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_existing_billing_period.json create mode 100644 tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_new_billing_period.json create mode 100644 tests/Functional/Resources/Subscriptions/_fixtures/request/resume_existing_billing_period.json create mode 100644 tests/Functional/Resources/Subscriptions/_fixtures/request/resume_new_billing_period.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b13a45..f0808f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 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. +## 1.4.0 - 2024-12-19 + +### Added + +- Added `on_resume` support to subscription resume and pause operations + ## 1.3.1 - 2024-12-17 ### Fixed diff --git a/paddle_billing/Client.py b/paddle_billing/Client.py index 04cf62b..51d128b 100644 --- a/paddle_billing/Client.py +++ b/paddle_billing/Client.py @@ -204,7 +204,7 @@ def build_request_session(self) -> Session: "Authorization": f"Bearer {self.__api_key}", "Content-Type": "application/json", "Paddle-Version": str(self.use_api_version), - "User-Agent": "PaddleSDK/python 1.3.1", + "User-Agent": "PaddleSDK/python 1.4.0", } ) diff --git a/paddle_billing/Entities/Subscriptions/SubscriptionOnResume.py b/paddle_billing/Entities/Subscriptions/SubscriptionOnResume.py new file mode 100644 index 0000000..9d09de0 --- /dev/null +++ b/paddle_billing/Entities/Subscriptions/SubscriptionOnResume.py @@ -0,0 +1,6 @@ +from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta + + +class SubscriptionOnResume(PaddleStrEnum, metaclass=PaddleStrEnumMeta): + ContinueExistingBillingPeriod: "SubscriptionOnResume" = "continue_existing_billing_period" + StartNewBillingPeriod: "SubscriptionOnResume" = "start_new_billing_period" diff --git a/paddle_billing/Entities/Subscriptions/__init__.py b/paddle_billing/Entities/Subscriptions/__init__.py index a10608f..106ace8 100644 --- a/paddle_billing/Entities/Subscriptions/__init__.py +++ b/paddle_billing/Entities/Subscriptions/__init__.py @@ -9,6 +9,7 @@ from paddle_billing.Entities.Subscriptions.SubscriptionManagementUrls import SubscriptionManagementUrls from paddle_billing.Entities.Subscriptions.SubscriptionNextTransaction import SubscriptionNextTransaction from paddle_billing.Entities.Subscriptions.SubscriptionOnPaymentFailure import SubscriptionOnPaymentFailure +from paddle_billing.Entities.Subscriptions.SubscriptionOnResume import SubscriptionOnResume from paddle_billing.Entities.Subscriptions.SubscriptionPreviewSubscriptionUpdateSummary import ( SubscriptionPreviewSubscriptionUpdateSummary, ) diff --git a/paddle_billing/Resources/Subscriptions/Operations/PauseSubscription.py b/paddle_billing/Resources/Subscriptions/Operations/PauseSubscription.py index 2e9ed95..176d549 100644 --- a/paddle_billing/Resources/Subscriptions/Operations/PauseSubscription.py +++ b/paddle_billing/Resources/Subscriptions/Operations/PauseSubscription.py @@ -2,10 +2,12 @@ from paddle_billing.Operation import Operation from paddle_billing.Entities.DateTime import DateTime -from paddle_billing.Entities.Subscriptions import SubscriptionEffectiveFrom +from paddle_billing.Entities.Subscriptions import SubscriptionEffectiveFrom, SubscriptionOnResume +from paddle_billing.Undefined import Undefined @dataclass class PauseSubscription(Operation): effective_from: SubscriptionEffectiveFrom | None = None resume_at: DateTime | None = None + on_resume: SubscriptionOnResume | Undefined = Undefined() diff --git a/paddle_billing/Resources/Subscriptions/Operations/ResumeSubscription.py b/paddle_billing/Resources/Subscriptions/Operations/ResumeSubscription.py index d337264..30c0658 100644 --- a/paddle_billing/Resources/Subscriptions/Operations/ResumeSubscription.py +++ b/paddle_billing/Resources/Subscriptions/Operations/ResumeSubscription.py @@ -2,9 +2,11 @@ from paddle_billing.Operation import Operation from paddle_billing.Entities.DateTime import DateTime -from paddle_billing.Entities.Subscriptions import SubscriptionResumeEffectiveFrom +from paddle_billing.Entities.Subscriptions import SubscriptionResumeEffectiveFrom, SubscriptionOnResume +from paddle_billing.Undefined import Undefined @dataclass class ResumeSubscription(Operation): effective_from: SubscriptionResumeEffectiveFrom | DateTime | None = None + on_resume: SubscriptionOnResume | Undefined = Undefined() diff --git a/setup.py b/setup.py index d13c6b9..3836540 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( - version="1.3.1", + version="1.4.0", author="Paddle and contributors", author_email="team-dx@paddle.com", description="Paddle's Python SDK for Paddle Billing", diff --git a/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_existing_billing_period.json b/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_existing_billing_period.json new file mode 100644 index 0000000..137597e --- /dev/null +++ b/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_existing_billing_period.json @@ -0,0 +1,5 @@ +{ + "effective_from": "next_billing_period", + "resume_at": "2023-10-09T16:30:00.000000Z", + "on_resume": "continue_existing_billing_period" +} diff --git a/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_new_billing_period.json b/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_new_billing_period.json new file mode 100644 index 0000000..023e1bd --- /dev/null +++ b/tests/Functional/Resources/Subscriptions/_fixtures/request/pause_resume_new_billing_period.json @@ -0,0 +1,5 @@ +{ + "effective_from": "next_billing_period", + "resume_at": "2023-10-09T16:30:00.000000Z", + "on_resume": "start_new_billing_period" +} diff --git a/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_existing_billing_period.json b/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_existing_billing_period.json new file mode 100644 index 0000000..b0d7757 --- /dev/null +++ b/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_existing_billing_period.json @@ -0,0 +1,4 @@ +{ + "effective_from": "immediately", + "on_resume": "continue_existing_billing_period" +} diff --git a/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_new_billing_period.json b/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_new_billing_period.json new file mode 100644 index 0000000..1a578ce --- /dev/null +++ b/tests/Functional/Resources/Subscriptions/_fixtures/request/resume_new_billing_period.json @@ -0,0 +1,4 @@ +{ + "effective_from": "immediately", + "on_resume": "start_new_billing_period" +} diff --git a/tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py b/tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py index 9c056c7..899695f 100644 --- a/tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py +++ b/tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py @@ -26,6 +26,7 @@ from paddle_billing.Entities.Subscriptions import ( SubscriptionEffectiveFrom, SubscriptionOnPaymentFailure, + SubscriptionOnResume, SubscriptionProrationBillingMode, SubscriptionResumeEffectiveFrom, SubscriptionScheduledChangeAction, @@ -516,11 +517,37 @@ def test_get_subscription_returns_transaction_line_item_proration( ReadsFixtures.read_raw_json_fixture("response/full_entity"), "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/pause", ), + ( + "sub_01h8bx8fmywym11t6swgzba704", + PauseSubscription( + SubscriptionEffectiveFrom.NextBillingPeriod, + DateTime("2023-10-09T16:30:00Z"), + SubscriptionOnResume.ContinueExistingBillingPeriod, + ), + ReadsFixtures.read_raw_json_fixture("request/pause_resume_existing_billing_period"), + 200, + ReadsFixtures.read_raw_json_fixture("response/full_entity"), + "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/pause", + ), + ( + "sub_01h8bx8fmywym11t6swgzba704", + PauseSubscription( + SubscriptionEffectiveFrom.NextBillingPeriod, + DateTime("2023-10-09T16:30:00Z"), + SubscriptionOnResume.StartNewBillingPeriod, + ), + ReadsFixtures.read_raw_json_fixture("request/pause_resume_new_billing_period"), + 200, + ReadsFixtures.read_raw_json_fixture("response/full_entity"), + "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/pause", + ), ], ids=[ "Pause subscription", "Pause subscription as of next billing period", "Pause subscription as of next billing period and resume at date", + "Pause subscription resume in existing billing period", + "Pause subscription resume in new billing period", ], ) def test_pause_subscription_uses_expected_payload( @@ -583,11 +610,33 @@ def test_pause_subscription_uses_expected_payload( ReadsFixtures.read_raw_json_fixture("response/full_entity"), "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/resume", ), + ( + "sub_01h8bx8fmywym11t6swgzba704", + ResumeSubscription( + SubscriptionResumeEffectiveFrom.Immediately, SubscriptionOnResume.ContinueExistingBillingPeriod + ), + ReadsFixtures.read_raw_json_fixture("request/resume_existing_billing_period"), + 200, + ReadsFixtures.read_raw_json_fixture("response/full_entity"), + "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/resume", + ), + ( + "sub_01h8bx8fmywym11t6swgzba704", + ResumeSubscription( + SubscriptionResumeEffectiveFrom.Immediately, SubscriptionOnResume.StartNewBillingPeriod + ), + ReadsFixtures.read_raw_json_fixture("request/resume_new_billing_period"), + 200, + ReadsFixtures.read_raw_json_fixture("response/full_entity"), + "/subscriptions/sub_01h8bx8fmywym11t6swgzba704/resume", + ), ], ids=[ "Resume subscription", "Resume subscription with a billing period", "Resume subscription with a new date", + "Resume subscription in existing billing period", + "Resume subscription in new billing period", ], ) def test_resume_subscription_uses_expected_payload(