Skip to content

Commit

Permalink
feat: Support custom prices when updating and previewing subscriptions (
Browse files Browse the repository at this point in the history
#27)

* feat: Support custom prices when updating and previewing subscriptions

* fix: Replace custom flattening of custom_data with to_json method
  • Loading branch information
davidgrayston-paddle committed Sep 20, 2024
1 parent d802d0b commit 17ea2ce
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 43 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ Check our main [developer changelog](https://developer.paddle.com/?utm_source=dx
### Added

- Added `product` to `subscription.items[]`, see [related changelog](https://developer.paddle.com/changelog/2024/subscription-items-product?utm_source=dx&utm_medium=paddle-python-sdk)
- Support custom prices when updating and previewing subscriptions, see [related changelog](https://developer.paddle.com/changelog/2024/add-custom-items-subscription)

### Changed

- `paddle_billing.Entities.Shared.CustomData` is no longer a `dataclass`

## 0.2.2 - 2024-09-03

Expand Down
4 changes: 0 additions & 4 deletions paddle_billing/Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ def logging_hook(self, response, *args, **kwargs):

@staticmethod
def serialize_json_payload(payload: dict) -> str:
# Removes unneeded level of nested CustomData data
if payload.get('custom_data') and 'data' in payload['custom_data']:
payload['custom_data'] = payload['custom_data']['data']

json_payload = json_dumps(payload, cls=PayloadEncoder)
final_json = json_payload if json_payload != '[]' else '{}'

Expand Down
12 changes: 8 additions & 4 deletions paddle_billing/Entities/Shared/CustomData.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from dataclasses import dataclass


@dataclass
class CustomData:
data: dict | list # JSON serializable Python types


def __init__(self, data: dict | list):
self.data = data


def get_parameters(self):
return self.data


def to_json(self):
return self.data
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import annotations
from dataclasses import dataclass
from dataclasses import asdict, dataclass

from paddle_billing.Entities.Subscriptions.SubscriptionNonCatalogPrice import SubscriptionNonCatalogPrice
from paddle_billing.Entities.Subscriptions.SubscriptionNonCatalogPriceWithProduct import SubscriptionNonCatalogPriceWithProduct
Expand All @@ -17,3 +17,7 @@ def from_dict(data: dict) -> SubscriptionItemsWithPrice:
price = data['price'],
quantity = data['quantity'],
)


def get_parameters(self) -> dict:
return asdict(self)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass

from paddle_billing.Entities.Shared import CustomData, Money, PriceQuantity, TaxMode, UnitPriceOverride
from paddle_billing.Entities.Shared import CustomData, Money, PriceQuantity, TaxMode, UnitPriceOverride, TimePeriod


@dataclass
Expand All @@ -14,6 +14,8 @@ class SubscriptionNonCatalogPrice:
unit_price_overrides: list[UnitPriceOverride]
quantity: PriceQuantity
custom_data: CustomData | None
billing_cycle: TimePeriod | None
trial_period: TimePeriod | None


@staticmethod
Expand All @@ -27,4 +29,6 @@ def from_dict(data: dict) -> SubscriptionNonCatalogPrice:
unit_price_overrides = [UnitPriceOverride.from_dict(override) for override in data['unit_price_overrides']],
quantity = PriceQuantity.from_dict(data['quantity']),
custom_data = CustomData(data['custom_data']) if data.get('custom_data') else None,
billing_cycle = TimePeriod.from_dict(data['billing_cycle']) if data.get('billing_cycle') else None,
trial_period = TimePeriod.from_dict(data['trial_period']) if data.get('trial_period') else None,
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass

from paddle_billing.Entities.Shared import CustomData, Money, PriceQuantity, TaxMode, UnitPriceOverride
from paddle_billing.Entities.Shared import CustomData, Money, PriceQuantity, TaxMode, UnitPriceOverride, TimePeriod

from paddle_billing.Entities.Subscriptions.SubscriptionNonCatalogProduct import SubscriptionNonCatalogProduct

Expand All @@ -16,6 +16,8 @@ class SubscriptionNonCatalogPriceWithProduct:
unit_price_overrides: list[UnitPriceOverride]
quantity: PriceQuantity
custom_data: CustomData | None
billing_cycle: TimePeriod | None
trial_period: TimePeriod | None


@staticmethod
Expand All @@ -29,4 +31,6 @@ def from_dict(data: dict) -> SubscriptionNonCatalogPriceWithProduct:
unit_price_overrides = [UnitPriceOverride.from_dict(override) for override in data['unit_price_overrides']],
quantity = PriceQuantity.from_dict(data['quantity']),
custom_data = CustomData(data['custom_data']) if data.get('custom_data') else None,
billing_cycle = TimePeriod.from_dict(data['billing_cycle']) if data.get('billing_cycle') else None,
trial_period = TimePeriod.from_dict(data['trial_period']) if data.get('trial_period') else None,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@

from paddle_billing.Entities.DateTime import DateTime
from paddle_billing.Entities.Shared import BillingDetails, CollectionMode, CurrencyCode, CustomData
from paddle_billing.Entities.Subscriptions import SubscriptionItems, SubscriptionOnPaymentFailure, SubscriptionProrationBillingMode
from paddle_billing.Entities.Subscriptions import SubscriptionItems, SubscriptionItemsWithPrice, SubscriptionOnPaymentFailure, SubscriptionProrationBillingMode, SubscriptionScheduledChange

from paddle_billing.Resources.Subscriptions.Operations.Update.SubscriptionDiscount import SubscriptionDiscount


@dataclass
class PreviewUpdateSubscription:
customer_id: str | Undefined = Undefined()
address_id: str | Undefined = Undefined()
business_id: str | None | Undefined = Undefined()
currency_code: CurrencyCode | Undefined = Undefined()
next_billed_at: DateTime | Undefined = Undefined()
discount: SubscriptionDiscount | None | Undefined = Undefined()
collection_mode: CollectionMode | Undefined = Undefined()
billing_details: BillingDetails | None | Undefined = Undefined()
scheduled_change: None | Undefined = Undefined()
items: list[SubscriptionItems] | Undefined = Undefined()
custom_data: CustomData | None | Undefined = Undefined()
proration_billing_mode: SubscriptionProrationBillingMode | Undefined = Undefined()
on_payment_failure: SubscriptionOnPaymentFailure | Undefined = Undefined()
customer_id: str | Undefined = Undefined()
address_id: str | Undefined = Undefined()
business_id: str | None | Undefined = Undefined()
currency_code: CurrencyCode | Undefined = Undefined()
next_billed_at: DateTime | Undefined = Undefined()
discount: SubscriptionDiscount | None | Undefined = Undefined()
collection_mode: CollectionMode | Undefined = Undefined()
billing_details: BillingDetails | None | Undefined = Undefined()
scheduled_change: None | Undefined = Undefined()
items: list[SubscriptionItems | SubscriptionItemsWithPrice] | Undefined = Undefined()
custom_data: CustomData | None | Undefined = Undefined()
proration_billing_mode: SubscriptionProrationBillingMode | Undefined = Undefined()
on_payment_failure: SubscriptionOnPaymentFailure | Undefined = Undefined()


def get_parameters(self) -> dict:
Expand All @@ -35,3 +35,4 @@ def get_parameters(self) -> dict:
parameters['items'] = [item.get_parameters() for item in self.items]

return parameters

Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@

from paddle_billing.Entities.DateTime import DateTime
from paddle_billing.Entities.Shared import BillingDetails, CollectionMode, CurrencyCode, CustomData
from paddle_billing.Entities.Subscriptions import SubscriptionItems, SubscriptionOnPaymentFailure, SubscriptionProrationBillingMode
from paddle_billing.Entities.Subscriptions import SubscriptionItems, SubscriptionItemsWithPrice, SubscriptionOnPaymentFailure, SubscriptionProrationBillingMode, SubscriptionScheduledChange

from paddle_billing.Resources.Subscriptions.Operations.Update.SubscriptionDiscount import SubscriptionDiscount


@dataclass
class UpdateSubscription:
customer_id: str | Undefined = Undefined()
address_id: str | Undefined = Undefined()
business_id: str | None | Undefined = Undefined()
currency_code: CurrencyCode | Undefined = Undefined()
next_billed_at: DateTime | Undefined = Undefined()
discount: SubscriptionDiscount | None | Undefined = Undefined()
collection_mode: CollectionMode | Undefined = Undefined()
billing_details: BillingDetails | None | Undefined = Undefined()
scheduled_change: None | Undefined = Undefined()
items: list[SubscriptionItems] | Undefined = Undefined()
custom_data: CustomData | None | Undefined = Undefined()
proration_billing_mode: SubscriptionProrationBillingMode | Undefined = Undefined()
on_payment_failure: SubscriptionOnPaymentFailure | Undefined = Undefined()
customer_id: str | Undefined = Undefined()
address_id: str | Undefined = Undefined()
business_id: str | None | Undefined = Undefined()
currency_code: CurrencyCode | Undefined = Undefined()
next_billed_at: DateTime | Undefined = Undefined()
discount: SubscriptionDiscount | None | Undefined = Undefined()
collection_mode: CollectionMode | Undefined = Undefined()
billing_details: BillingDetails | None | Undefined = Undefined()
scheduled_change: None | Undefined = Undefined()
items: list[SubscriptionItems | SubscriptionItemsWithPrice] | Undefined = Undefined()
custom_data: CustomData | None | Undefined = Undefined()
proration_billing_mode: SubscriptionProrationBillingMode | Undefined = Undefined()
on_payment_failure: SubscriptionOnPaymentFailure | Undefined = Undefined()


def get_parameters(self) -> dict:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,74 @@
"scheduled_change": null,
"items": [
{ "price_id": "pri_01gsz91wy9k1yn7kx82aafwvea", "quantity": 1 },
{ "price_id": "pri_01gsz91wy9k1yn7kx82bafwvea", "quantity": 5 }
{ "price_id": "pri_01gsz91wy9k1yn7kx82bafwvea", "quantity": 5 },
{
"price": {
"custom_data": {
"key": "value"
},
"description": "some description",
"name": "some name",
"product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
"quantity": {
"maximum": 3,
"minimum": 1
},
"tax_mode": "account_setting",
"unit_price": {
"amount": "1",
"currency_code": "GBP"
},
"unit_price_overrides": [],
"billing_cycle": {
"frequency": 1,
"interval": "day"
},
"trial_period": {
"frequency": 2,
"interval": "day"
}
},
"quantity": 2
},
{
"price": {
"custom_data": {
"key": "value"
},
"description": "some description",
"name": "some name",
"product": {
"custom_data": {
"key": "value"
},
"description": "some description",
"image_url": "https://www.example.com/image.jpg",
"name": "some name",
"tax_category": "digital-goods",
"type": "custom"
},
"quantity": {
"maximum": 3,
"minimum": 1
},
"tax_mode": "account_setting",
"unit_price": {
"amount": "1",
"currency_code": "GBP"
},
"unit_price_overrides": [],
"billing_cycle": {
"frequency": 1,
"interval": "day"
},
"trial_period": {
"frequency": 2,
"interval": "day"
}
},
"quantity": 2
}
],
"proration_billing_mode": "full_immediately",
"custom_data": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,74 @@
"scheduled_change": null,
"items": [
{ "price_id": "pri_01gsz91wy9k1yn7kx82aafwvea", "quantity": 1 },
{ "price_id": "pri_01gsz91wy9k1yn7kx82bafwvea", "quantity": 5 }
{ "price_id": "pri_01gsz91wy9k1yn7kx82bafwvea", "quantity": 5 },
{
"price": {
"custom_data": {
"key": "value"
},
"description": "some description",
"name": "some name",
"product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
"quantity": {
"maximum": 3,
"minimum": 1
},
"tax_mode": "account_setting",
"unit_price": {
"amount": "1",
"currency_code": "GBP"
},
"unit_price_overrides": [],
"billing_cycle": {
"frequency": 1,
"interval": "day"
},
"trial_period": {
"frequency": 2,
"interval": "day"
}
},
"quantity": 2
},
{
"price": {
"custom_data": {
"key": "value"
},
"description": "some description",
"name": "some name",
"product": {
"custom_data": {
"key": "value"
},
"description": "some description",
"image_url": "https://www.example.com/image.jpg",
"name": "some name",
"tax_category": "digital-goods",
"type": "custom"
},
"quantity": {
"maximum": 3,
"minimum": 1
},
"tax_mode": "account_setting",
"unit_price": {
"amount": "1",
"currency_code": "GBP"
},
"unit_price_overrides": [],
"billing_cycle": {
"frequency": 1,
"interval": "day"
},
"trial_period": {
"frequency": 2,
"interval": "day"
}
},
"quantity": 2
}
],
"proration_billing_mode": "full_immediately",
"custom_data": {
Expand Down
Loading

0 comments on commit 17ea2ce

Please sign in to comment.