paddle-python-sdk 1.4.0__py3-none-any.whl → 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. paddle_billing/Client.py +11 -23
  2. paddle_billing/Entities/Collections/SimulationCollection.py +13 -0
  3. paddle_billing/Entities/Collections/SimulationRunCollection.py +13 -0
  4. paddle_billing/Entities/Collections/SimulationRunEventCollection.py +13 -0
  5. paddle_billing/Entities/Collections/SimulationTypeCollection.py +13 -0
  6. paddle_billing/Entities/Collections/__init__.py +4 -0
  7. paddle_billing/Entities/Events/EventTypeName.py +3 -0
  8. paddle_billing/Entities/Simulation.py +46 -0
  9. paddle_billing/Entities/SimulationRun.py +35 -0
  10. paddle_billing/Entities/SimulationRunEvent.py +40 -0
  11. paddle_billing/Entities/SimulationRunEvents/SimulationRunEventRequest.py +15 -0
  12. paddle_billing/Entities/SimulationRunEvents/SimulationRunEventResponse.py +17 -0
  13. paddle_billing/Entities/SimulationRunEvents/SimulationRunEventStatus.py +8 -0
  14. paddle_billing/Entities/SimulationRunEvents/__init__.py +3 -0
  15. paddle_billing/Entities/SimulationRuns/SimulationRunStatus.py +7 -0
  16. paddle_billing/Entities/SimulationRuns/__init__.py +1 -0
  17. paddle_billing/Entities/SimulationType.py +28 -0
  18. paddle_billing/Entities/Simulations/SimulationKind.py +6 -0
  19. paddle_billing/Entities/Simulations/SimulationScenarioType.py +9 -0
  20. paddle_billing/Entities/Simulations/SimulationStatus.py +6 -0
  21. paddle_billing/Entities/Simulations/__init__.py +3 -0
  22. paddle_billing/Entities/Transaction.py +2 -0
  23. paddle_billing/Json/JsonExclude.py +6 -0
  24. paddle_billing/Json/JsonFormatProperties.py +6 -0
  25. paddle_billing/Json/PayloadEncoder.py +42 -0
  26. paddle_billing/Json/__init__.py +3 -0
  27. paddle_billing/Notifications/Entities/Entity.py +1 -1
  28. paddle_billing/Notifications/Entities/Price.py +0 -4
  29. paddle_billing/Notifications/Entities/Product.py +3 -1
  30. paddle_billing/Notifications/Entities/Simulations/Address.py +52 -0
  31. paddle_billing/Notifications/Entities/Simulations/Adjustment.py +68 -0
  32. paddle_billing/Notifications/Entities/Simulations/Business.py +51 -0
  33. paddle_billing/Notifications/Entities/Simulations/Customer.py +44 -0
  34. paddle_billing/Notifications/Entities/Simulations/Discount.py +67 -0
  35. paddle_billing/Notifications/Entities/Simulations/PaymentMethod.py +33 -0
  36. paddle_billing/Notifications/Entities/Simulations/PaymentMethodDeleted.py +40 -0
  37. paddle_billing/Notifications/Entities/Simulations/Payout.py +24 -0
  38. paddle_billing/Notifications/Entities/Simulations/Price.py +86 -0
  39. paddle_billing/Notifications/Entities/Simulations/Product.py +54 -0
  40. paddle_billing/Notifications/Entities/Simulations/Report.py +48 -0
  41. paddle_billing/Notifications/Entities/Simulations/SimulationEntity.py +43 -0
  42. paddle_billing/Notifications/Entities/Simulations/Subscription.py +124 -0
  43. paddle_billing/Notifications/Entities/Simulations/SubscriptionCreated.py +126 -0
  44. paddle_billing/Notifications/Entities/Simulations/Transaction.py +105 -0
  45. paddle_billing/Notifications/Entities/Simulations/__init__.py +14 -0
  46. paddle_billing/Notifications/Entities/Transaction.py +2 -0
  47. paddle_billing/Notifications/Entities/Transactions/TransactionDetails.py +3 -0
  48. paddle_billing/Notifications/Entities/Transactions/TransactionItem.py +3 -1
  49. paddle_billing/Notifications/Events/TransactionRevised.py +17 -0
  50. paddle_billing/Resources/SimulationRunEvents/Operations/ListSimulationRunEvents.py +32 -0
  51. paddle_billing/Resources/SimulationRunEvents/Operations/__init__.py +1 -0
  52. paddle_billing/Resources/SimulationRunEvents/SimulationRunEventsClient.py +45 -0
  53. paddle_billing/Resources/SimulationRunEvents/__init__.py +0 -0
  54. paddle_billing/Resources/SimulationRuns/Operations/GetSimulationRun.py +29 -0
  55. paddle_billing/Resources/SimulationRuns/Operations/ListSimulationRuns.py +39 -0
  56. paddle_billing/Resources/SimulationRuns/Operations/SimulationRunInclude.py +5 -0
  57. paddle_billing/Resources/SimulationRuns/Operations/__init__.py +3 -0
  58. paddle_billing/Resources/SimulationRuns/SimulationRunsClient.py +42 -0
  59. paddle_billing/Resources/SimulationRuns/__init__.py +0 -0
  60. paddle_billing/Resources/SimulationTypes/SimulationTypesClient.py +19 -0
  61. paddle_billing/Resources/SimulationTypes/__init__.py +0 -0
  62. paddle_billing/Resources/Simulations/Operations/CreateSimulation.py +17 -0
  63. paddle_billing/Resources/Simulations/Operations/ListSimulations.py +47 -0
  64. paddle_billing/Resources/Simulations/Operations/UpdateSimulation.py +18 -0
  65. paddle_billing/Resources/Simulations/Operations/__init__.py +3 -0
  66. paddle_billing/Resources/Simulations/SimulationsClient.py +45 -0
  67. paddle_billing/Resources/Simulations/__init__.py +0 -0
  68. paddle_billing/Resources/Transactions/Operations/Revise/ReviseAddress.py +12 -0
  69. paddle_billing/Resources/Transactions/Operations/Revise/ReviseBusiness.py +10 -0
  70. paddle_billing/Resources/Transactions/Operations/Revise/ReviseCustomer.py +9 -0
  71. paddle_billing/Resources/Transactions/Operations/Revise/__init__.py +3 -0
  72. paddle_billing/Resources/Transactions/Operations/ReviseTransaction.py +16 -0
  73. paddle_billing/Resources/Transactions/Operations/__init__.py +1 -0
  74. paddle_billing/Resources/Transactions/TransactionsClient.py +7 -0
  75. {paddle_python_sdk-1.4.0.dist-info → paddle_python_sdk-1.5.0.dist-info}/METADATA +14 -2
  76. {paddle_python_sdk-1.4.0.dist-info → paddle_python_sdk-1.5.0.dist-info}/RECORD +90 -20
  77. {paddle_python_sdk-1.4.0.dist-info → paddle_python_sdk-1.5.0.dist-info}/WHEEL +1 -1
  78. tests/Functional/Resources/Notifications/test_NotificationsClient.py +22 -1
  79. tests/Functional/Resources/SimulationRunEvents/__init__.py +0 -0
  80. tests/Functional/Resources/SimulationRunEvents/test_SimulationRunEventsClient.py +265 -0
  81. tests/Functional/Resources/SimulationRuns/__init__.py +0 -0
  82. tests/Functional/Resources/SimulationRuns/test_SimulationRunsClient.py +201 -0
  83. tests/Functional/Resources/SimulationTypes/__init__.py +0 -0
  84. tests/Functional/Resources/SimulationTypes/test_SimulationTypesClient.py +68 -0
  85. tests/Functional/Resources/Simulations/__init__.py +0 -0
  86. tests/Functional/Resources/Simulations/test_SimulationsClient.py +589 -0
  87. tests/Functional/Resources/Transactions/test_TransactionsClient.py +122 -0
  88. tests/Utils/ReadsFixture.py +4 -0
  89. {paddle_python_sdk-1.4.0.dist-info → paddle_python_sdk-1.5.0.dist-info}/LICENSE +0 -0
  90. {paddle_python_sdk-1.4.0.dist-info → paddle_python_sdk-1.5.0.dist-info}/top_level.txt +0 -0
paddle_billing/Client.py CHANGED
@@ -1,15 +1,13 @@
1
- from json import dumps as json_dumps, JSONEncoder
1
+ from json import dumps as json_dumps
2
2
  from logging import Logger, getLogger
3
3
  from requests import Response, RequestException, Session
4
4
  from requests.adapters import HTTPAdapter
5
5
  from urllib3.util.retry import Retry
6
6
  from urllib.parse import urljoin, urlencode
7
7
  from uuid import uuid4
8
- from dataclasses import fields, is_dataclass
8
+ from paddle_billing.Json import PayloadEncoder
9
9
 
10
10
  from paddle_billing.Operation import Operation
11
- from paddle_billing.FiltersUndefined import FiltersUndefined
12
- from paddle_billing.Undefined import Undefined
13
11
  from paddle_billing.HasParameters import HasParameters
14
12
  from paddle_billing.Options import Options
15
13
  from paddle_billing.ResponseParser import ResponseParser
@@ -33,28 +31,14 @@ from paddle_billing.Resources.Prices.PricesClient import PricesClient
33
31
  from paddle_billing.Resources.PricingPreviews.PricingPreviewsClient import PricingPreviewsClient
34
32
  from paddle_billing.Resources.Products.ProductsClient import ProductsClient
35
33
  from paddle_billing.Resources.Reports.ReportsClient import ReportsClient
34
+ from paddle_billing.Resources.Simulations.SimulationsClient import SimulationsClient
35
+ from paddle_billing.Resources.SimulationRuns.SimulationRunsClient import SimulationRunsClient
36
+ from paddle_billing.Resources.SimulationRunEvents.SimulationRunEventsClient import SimulationRunEventsClient
37
+ from paddle_billing.Resources.SimulationTypes.SimulationTypesClient import SimulationTypesClient
36
38
  from paddle_billing.Resources.Subscriptions.SubscriptionsClient import SubscriptionsClient
37
39
  from paddle_billing.Resources.Transactions.TransactionsClient import TransactionsClient
38
40
 
39
41
 
40
- class PayloadEncoder(JSONEncoder):
41
- def default(self, z):
42
- if isinstance(z, Undefined):
43
- return None
44
-
45
- if hasattr(z, "to_json") and callable(z.to_json):
46
- return z.to_json()
47
-
48
- if is_dataclass(z):
49
- data = {}
50
- for field in fields(z):
51
- data[field.name] = getattr(z, field.name)
52
-
53
- return FiltersUndefined.filter_undefined_values(data)
54
-
55
- return super().default(z)
56
-
57
-
58
42
  class Client:
59
43
  """
60
44
  Client for making API requests using Python's requests library.
@@ -98,6 +82,10 @@ class Client:
98
82
  self.pricing_previews = PricingPreviewsClient(self)
99
83
  self.products = ProductsClient(self)
100
84
  self.reports = ReportsClient(self)
85
+ self.simulations = SimulationsClient(self)
86
+ self.simulation_runs = SimulationRunsClient(self)
87
+ self.simulation_run_events = SimulationRunEventsClient(self)
88
+ self.simulation_types = SimulationTypesClient(self)
101
89
  self.subscriptions = SubscriptionsClient(self)
102
90
  self.transactions = TransactionsClient(self)
103
91
  self.ip_addresses = IPAddressesClient(self)
@@ -204,7 +192,7 @@ class Client:
204
192
  "Authorization": f"Bearer {self.__api_key}",
205
193
  "Content-Type": "application/json",
206
194
  "Paddle-Version": str(self.use_api_version),
207
- "User-Agent": "PaddleSDK/python 1.4.0",
195
+ "User-Agent": "PaddleSDK/python 1.5.0",
208
196
  }
209
197
  )
210
198
 
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from paddle_billing.Entities.Collections.Collection import Collection
4
+ from paddle_billing.Entities.Collections.Paginator import Paginator
5
+ from paddle_billing.Entities.Simulation import Simulation
6
+
7
+
8
+ class SimulationCollection(Collection[Simulation]):
9
+ @classmethod
10
+ def from_list(cls, items_data: list, paginator: Paginator | None = None) -> SimulationCollection:
11
+ items: list[Simulation] = [Simulation.from_dict(item) for item in items_data]
12
+
13
+ return SimulationCollection(items, paginator)
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from paddle_billing.Entities.Collections.Collection import Collection
4
+ from paddle_billing.Entities.Collections.Paginator import Paginator
5
+ from paddle_billing.Entities.SimulationRun import SimulationRun
6
+
7
+
8
+ class SimulationRunCollection(Collection[SimulationRun]):
9
+ @classmethod
10
+ def from_list(cls, items_data: list, paginator: Paginator | None = None) -> SimulationRunCollection:
11
+ items: list[SimulationRun] = [SimulationRun.from_dict(item) for item in items_data]
12
+
13
+ return SimulationRunCollection(items, paginator)
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from paddle_billing.Entities.Collections.Collection import Collection
4
+ from paddle_billing.Entities.Collections.Paginator import Paginator
5
+ from paddle_billing.Entities.SimulationRunEvent import SimulationRunEvent
6
+
7
+
8
+ class SimulationRunEventCollection(Collection[SimulationRunEvent]):
9
+ @classmethod
10
+ def from_list(cls, items_data: list, paginator: Paginator | None = None) -> SimulationRunEventCollection:
11
+ items: list[SimulationRunEvent] = [SimulationRunEvent.from_dict(item) for item in items_data]
12
+
13
+ return SimulationRunEventCollection(items, paginator)
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from paddle_billing.Entities.Collections.Collection import Collection
4
+ from paddle_billing.Entities.Collections.Paginator import Paginator
5
+ from paddle_billing.Entities.SimulationType import SimulationType
6
+
7
+
8
+ class SimulationTypeCollection(Collection[SimulationType]):
9
+ @classmethod
10
+ def from_list(cls, items_data: list, paginator: Paginator | None = None) -> SimulationTypeCollection:
11
+ items: list[SimulationType] = [SimulationType.from_dict(item) for item in items_data]
12
+
13
+ return SimulationTypeCollection(items, paginator)
@@ -15,6 +15,10 @@ from paddle_billing.Entities.Collections.PaymentMethodCollection import PaymentM
15
15
  from paddle_billing.Entities.Collections.PriceCollection import PriceCollection
16
16
  from paddle_billing.Entities.Collections.ProductCollection import ProductCollection
17
17
  from paddle_billing.Entities.Collections.ReportCollection import ReportCollection
18
+ from paddle_billing.Entities.Collections.SimulationCollection import SimulationCollection
19
+ from paddle_billing.Entities.Collections.SimulationRunCollection import SimulationRunCollection
20
+ from paddle_billing.Entities.Collections.SimulationRunEventCollection import SimulationRunEventCollection
21
+ from paddle_billing.Entities.Collections.SimulationTypeCollection import SimulationTypeCollection
18
22
  from paddle_billing.Entities.Collections.SubscriptionCollection import SubscriptionCollection
19
23
  from paddle_billing.Entities.Collections.SubscriptionPreviewCollection import SubscriptionPreviewCollection
20
24
  from paddle_billing.Entities.Collections.TransactionCollection import TransactionCollection
@@ -22,6 +22,8 @@ class EventTypeName(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
22
22
  InvoiceOverdue: "EventTypeName" = "invoice.overdue"
23
23
  InvoicePaid: "EventTypeName" = "invoice.paid"
24
24
  InvoiceScheduled: "EventTypeName" = "invoice.scheduled"
25
+ PaymentMethodDeleted: "EventTypeName" = "payment_method.deleted"
26
+ PaymentMethodSaved: "EventTypeName" = "payment_method.saved"
25
27
  PayoutCreated: "EventTypeName" = "payout.created"
26
28
  PayoutPaid: "EventTypeName" = "payout.paid"
27
29
  PriceCreated: "EventTypeName" = "price.created"
@@ -47,6 +49,7 @@ class EventTypeName(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
47
49
  TransactionPastDue: "EventTypeName" = "transaction.past_due"
48
50
  TransactionPaymentFailed: "EventTypeName" = "transaction.payment_failed"
49
51
  TransactionReady: "EventTypeName" = "transaction.ready"
52
+ TransactionRevised: "EventTypeName" = "transaction.revised"
50
53
  TransactionUpdated: "EventTypeName" = "transaction.updated"
51
54
  ReportCreated: "EventTypeName" = "report.created"
52
55
  ReportUpdated: "EventTypeName" = "report.updated"
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+ from abc import ABC
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+
6
+ from paddle_billing.Entities.Entity import Entity
7
+ from paddle_billing.Entities.Events import EventTypeName
8
+ from paddle_billing.Entities.Simulations import SimulationScenarioType, SimulationStatus
9
+
10
+ from paddle_billing.Notifications.Entities.Simulations.SimulationEntity import SimulationEntity
11
+ from paddle_billing.Notifications.Entities.UndefinedEntity import UndefinedEntity
12
+
13
+
14
+ @dataclass
15
+ class Simulation(Entity, ABC):
16
+ id: str
17
+ status: SimulationStatus
18
+ notification_setting_id: str
19
+ name: str
20
+ type: EventTypeName | SimulationScenarioType
21
+ payload: SimulationEntity | UndefinedEntity | None
22
+ last_run_at: datetime | None
23
+ created_at: datetime
24
+ updated_at: datetime
25
+
26
+ @staticmethod
27
+ def from_dict(data: dict) -> Simulation:
28
+ type = EventTypeName(data["type"])
29
+ if not type.is_known():
30
+ type = SimulationScenarioType(data["type"])
31
+
32
+ return Simulation(
33
+ id=data["id"],
34
+ status=SimulationStatus(data["status"]),
35
+ notification_setting_id=data["notification_setting_id"],
36
+ name=data["name"],
37
+ type=type,
38
+ payload=(
39
+ SimulationEntity.from_dict_for_event_type(data["payload"], type.value)
40
+ if isinstance(type, EventTypeName) and data.get("payload")
41
+ else None
42
+ ),
43
+ last_run_at=datetime.fromisoformat(data["last_run_at"]) if data.get("last_run_at") else None,
44
+ created_at=datetime.fromisoformat(data["created_at"]),
45
+ updated_at=datetime.fromisoformat(data["updated_at"]),
46
+ )
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+ from abc import ABC
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+
6
+ from paddle_billing.Entities.Entity import Entity
7
+ from paddle_billing.Entities.Events import EventTypeName
8
+ from paddle_billing.Entities.Simulations import SimulationScenarioType
9
+ from paddle_billing.Entities.SimulationRuns import SimulationRunStatus
10
+ from paddle_billing.Entities.SimulationRunEvent import SimulationRunEvent
11
+
12
+
13
+ @dataclass
14
+ class SimulationRun(Entity, ABC):
15
+ id: str
16
+ status: SimulationRunStatus
17
+ type: EventTypeName | SimulationScenarioType
18
+ created_at: datetime
19
+ updated_at: datetime
20
+ events: list[SimulationRunEvent]
21
+
22
+ @staticmethod
23
+ def from_dict(data: dict) -> SimulationRun:
24
+ type = EventTypeName(data["type"])
25
+ if not type.is_known():
26
+ type = SimulationScenarioType(data["type"])
27
+
28
+ return SimulationRun(
29
+ id=data["id"],
30
+ status=SimulationRunStatus(data["status"]),
31
+ type=type,
32
+ created_at=datetime.fromisoformat(data["created_at"]),
33
+ updated_at=datetime.fromisoformat(data["updated_at"]),
34
+ events=[SimulationRunEvent.from_dict(event) for event in data.get("events", [])],
35
+ )
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+ from abc import ABC
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+
6
+ from paddle_billing.Entities.Entity import Entity
7
+ from paddle_billing.Entities.Events import EventTypeName
8
+ from paddle_billing.Entities.SimulationRunEvents import (
9
+ SimulationRunEventStatus,
10
+ SimulationRunEventRequest,
11
+ SimulationRunEventResponse,
12
+ )
13
+
14
+ from paddle_billing.Notifications.Entities.Entity import Entity as NotificationEntity
15
+ from paddle_billing.Notifications.Entities.UndefinedEntity import UndefinedEntity
16
+
17
+
18
+ @dataclass
19
+ class SimulationRunEvent(Entity, ABC):
20
+ id: str
21
+ status: SimulationRunEventStatus
22
+ event_type: EventTypeName
23
+ payload: NotificationEntity | UndefinedEntity
24
+ request: SimulationRunEventRequest | None
25
+ response: SimulationRunEventResponse | None
26
+ created_at: datetime
27
+ updated_at: datetime
28
+
29
+ @staticmethod
30
+ def from_dict(data: dict) -> SimulationRunEvent:
31
+ return SimulationRunEvent(
32
+ id=data["id"],
33
+ status=SimulationRunEventStatus(data["status"]),
34
+ event_type=EventTypeName(data["event_type"]),
35
+ payload=NotificationEntity.from_dict_for_event_type(data["payload"], data["event_type"]),
36
+ request=SimulationRunEventRequest.from_dict(data["request"]) if data.get("request") else None,
37
+ response=SimulationRunEventResponse.from_dict(data["response"]) if data.get("response") else None,
38
+ created_at=datetime.fromisoformat(data["created_at"]),
39
+ updated_at=datetime.fromisoformat(data["updated_at"]),
40
+ )
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+ from paddle_billing.Entities.Entity import Entity
5
+
6
+
7
+ @dataclass
8
+ class SimulationRunEventRequest(Entity):
9
+ body: str
10
+
11
+ @staticmethod
12
+ def from_dict(data: dict) -> SimulationRunEventRequest:
13
+ return SimulationRunEventRequest(
14
+ body=data["body"],
15
+ )
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+ from paddle_billing.Entities.Entity import Entity
5
+
6
+
7
+ @dataclass
8
+ class SimulationRunEventResponse(Entity):
9
+ body: str
10
+ status_code: int
11
+
12
+ @staticmethod
13
+ def from_dict(data: dict) -> SimulationRunEventResponse:
14
+ return SimulationRunEventResponse(
15
+ body=data["body"],
16
+ status_code=data["status_code"],
17
+ )
@@ -0,0 +1,8 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class SimulationRunEventStatus(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Aborted: "SimulationRunEventStatus" = "aborted"
6
+ Failed: "SimulationRunEventStatus" = "failed"
7
+ Success: "SimulationRunEventStatus" = "success"
8
+ Pending: "SimulationRunEventStatus" = "pending"
@@ -0,0 +1,3 @@
1
+ from paddle_billing.Entities.SimulationRunEvents.SimulationRunEventRequest import SimulationRunEventRequest
2
+ from paddle_billing.Entities.SimulationRunEvents.SimulationRunEventResponse import SimulationRunEventResponse
3
+ from paddle_billing.Entities.SimulationRunEvents.SimulationRunEventStatus import SimulationRunEventStatus
@@ -0,0 +1,7 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class SimulationRunStatus(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Canceled: "SimulationRunStatus" = "canceled"
6
+ Completed: "SimulationRunStatus" = "completed"
7
+ Pending: "SimulationRunStatus" = "pending"
@@ -0,0 +1 @@
1
+ from paddle_billing.Entities.SimulationRuns.SimulationRunStatus import SimulationRunStatus
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+ from abc import ABC
3
+ from dataclasses import dataclass
4
+
5
+ from paddle_billing.Entities.Entity import Entity
6
+ from paddle_billing.Entities.Events import EventTypeName
7
+ from paddle_billing.Entities.Simulations import SimulationKind
8
+
9
+
10
+ @dataclass
11
+ class SimulationType(Entity, ABC):
12
+ name: str
13
+ label: str
14
+ description: str
15
+ group: str
16
+ type: SimulationKind
17
+ events: list[EventTypeName]
18
+
19
+ @staticmethod
20
+ def from_dict(data: dict) -> SimulationType:
21
+ return SimulationType(
22
+ name=data["name"],
23
+ label=data["label"],
24
+ description=data["description"],
25
+ group=data["group"],
26
+ type=SimulationKind(data["type"]),
27
+ events=[EventTypeName(event) for event in data.get("events", [])],
28
+ )
@@ -0,0 +1,6 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class SimulationKind(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Scenario: "SimulationKind" = "scenario"
6
+ SingleEvent: "SimulationKind" = "single_event"
@@ -0,0 +1,9 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class SimulationScenarioType(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ SubscriptionCreation: "SimulationScenarioType" = "subscription_creation"
6
+ SubscriptionRenewal: "SimulationScenarioType" = "subscription_renewal"
7
+ SubscriptionPause: "SimulationScenarioType" = "subscription_pause"
8
+ SubscriptionResume: "SimulationScenarioType" = "subscription_resume"
9
+ SubscriptionCancellation: "SimulationScenarioType" = "subscription_cancellation"
@@ -0,0 +1,6 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class SimulationStatus(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ Active: "SimulationStatus" = "active"
6
+ Archived: "SimulationStatus" = "archived"
@@ -0,0 +1,3 @@
1
+ from paddle_billing.Entities.Simulations.SimulationKind import SimulationKind
2
+ from paddle_billing.Entities.Simulations.SimulationScenarioType import SimulationScenarioType
3
+ from paddle_billing.Entities.Simulations.SimulationStatus import SimulationStatus
@@ -58,6 +58,7 @@ class Transaction(Entity):
58
58
  customer: Customer | None = None
59
59
  discount: Discount | None = None
60
60
  available_payment_methods: list[PaymentMethodType] | None = None
61
+ revised_at: datetime | None = None
61
62
 
62
63
  @staticmethod
63
64
  def from_dict(data: dict) -> Transaction:
@@ -95,4 +96,5 @@ class Transaction(Entity):
95
96
  if data.get("adjustment_totals")
96
97
  else None
97
98
  ),
99
+ revised_at=datetime.fromisoformat(data["revised_at"]) if data.get("revised_at") else None,
98
100
  )
@@ -0,0 +1,6 @@
1
+ def json_exclude(properties: list[str]):
2
+ def wrapper(cls):
3
+ cls.json_exclude_properties = properties
4
+ return cls
5
+
6
+ return wrapper
@@ -0,0 +1,6 @@
1
+ def json_format_properties(properties: list[str]):
2
+ def wrapper(cls):
3
+ cls.json_format_properties = properties
4
+ return cls
5
+
6
+ return wrapper
@@ -0,0 +1,42 @@
1
+ from json import JSONEncoder
2
+ from dataclasses import fields, is_dataclass
3
+ from datetime import datetime
4
+ import re
5
+
6
+ from paddle_billing.Entities.DateTime import DateTime
7
+ from paddle_billing.FiltersUndefined import FiltersUndefined
8
+ from paddle_billing.Undefined import Undefined
9
+
10
+
11
+ class PayloadEncoder(JSONEncoder):
12
+ def default(self, z):
13
+ if isinstance(z, Undefined):
14
+ return None
15
+
16
+ if isinstance(z, datetime):
17
+ return DateTime.from_datetime(z)
18
+
19
+ if hasattr(z, "to_json") and callable(z.to_json):
20
+ return z.to_json()
21
+
22
+ if is_dataclass(z):
23
+ exclude_properties = getattr(z.__class__, "json_exclude_properties", [])
24
+ format_properties = getattr(z.__class__, "json_format_properties", None)
25
+
26
+ data = {}
27
+ for field in fields(z):
28
+ key = (
29
+ self._camel_to_snake(field.name)
30
+ if format_properties and field.name in format_properties
31
+ else field.name
32
+ )
33
+
34
+ if field.name not in exclude_properties:
35
+ data[key] = getattr(z, field.name)
36
+
37
+ return FiltersUndefined.filter_undefined_values(data)
38
+
39
+ return super().default(z)
40
+
41
+ def _camel_to_snake(self, name: str) -> str:
42
+ return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
@@ -0,0 +1,3 @@
1
+ from paddle_billing.Json.JsonExclude import json_exclude
2
+ from paddle_billing.Json.JsonFormatProperties import json_format_properties
3
+ from paddle_billing.Json.PayloadEncoder import PayloadEncoder
@@ -36,7 +36,7 @@ class Entity(ABC, EntityDict):
36
36
  return UndefinedEntity(data)
37
37
 
38
38
  if not issubclass(entity_class, Entity):
39
- raise ValueError(f"Event type '{entity_class_name}' is not of NotificationEntity")
39
+ raise ValueError(f"Event type '{entity_class_name}' is not of Entity")
40
40
 
41
41
  return instantiated_class
42
42
 
@@ -57,7 +57,3 @@ class Price(Entity):
57
57
  created_at=datetime.fromisoformat(data["created_at"]) if data.get("created_at") else None,
58
58
  updated_at=datetime.fromisoformat(data["updated_at"]) if data.get("updated_at") else None,
59
59
  )
60
-
61
-
62
- # Prevents circular import
63
- from paddle_billing.Entities.Product import Product # noqa E402
@@ -4,9 +4,11 @@ from datetime import datetime
4
4
 
5
5
  from paddle_billing.Notifications.Entities.Entity import Entity
6
6
  from paddle_billing.Notifications.Entities.Shared import CatalogType, CustomData, ImportMeta, Status, TaxCategory
7
+ from paddle_billing.Json import json_exclude
7
8
 
8
9
 
9
10
  @dataclass
11
+ @json_exclude(["prices"])
10
12
  class Product(Entity):
11
13
  id: str
12
14
  name: str
@@ -16,7 +18,7 @@ class Product(Entity):
16
18
  image_url: str | None
17
19
  custom_data: CustomData | None = None
18
20
  import_meta: ImportMeta | None = None
19
- prices: list[Price] | None = None
21
+ prices: list[Price] | None = None # Deprecated: prices are not included in product notifications.
20
22
  type: CatalogType | None = None
21
23
  created_at: datetime | None = None
22
24
  updated_at: datetime | None = None
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from datetime import datetime
4
+
5
+ from paddle_billing.Undefined import Undefined
6
+ from paddle_billing.Notifications.Entities.Shared import CountryCode, CustomData, ImportMeta, Status
7
+ from paddle_billing.Notifications.Entities.Simulations.SimulationEntity import SimulationEntity
8
+
9
+
10
+ @dataclass
11
+ class Address(SimulationEntity):
12
+ id: str | Undefined = Undefined()
13
+ description: str | None | Undefined = Undefined()
14
+ first_line: str | None | Undefined = Undefined()
15
+ second_line: str | None | Undefined = Undefined()
16
+ city: str | None | Undefined = Undefined()
17
+ postal_code: str | None | Undefined = Undefined()
18
+ region: str | None | Undefined = Undefined()
19
+ country_code: CountryCode | Undefined = Undefined()
20
+ status: Status | Undefined = Undefined()
21
+ created_at: datetime | Undefined = Undefined()
22
+ updated_at: datetime | Undefined = Undefined()
23
+ custom_data: CustomData | None | Undefined = Undefined()
24
+ import_meta: ImportMeta | None | Undefined = Undefined()
25
+ customer_id: str | None | Undefined = Undefined()
26
+
27
+ @staticmethod
28
+ def from_dict(data: dict) -> Address:
29
+ return Address(
30
+ id=data.get("id", Undefined()),
31
+ customer_id=data.get("customer_id", Undefined()),
32
+ description=data.get("description", Undefined()),
33
+ first_line=data.get("first_line", Undefined()),
34
+ second_line=data.get("second_line", Undefined()),
35
+ city=data.get("city", Undefined()),
36
+ postal_code=data.get("postal_code", Undefined()),
37
+ region=data.get("region", Undefined()),
38
+ country_code=CountryCode(data["country_code"]) if data.get("country_code") else Undefined(),
39
+ status=Status(data["status"]) if data.get("status") else Undefined(),
40
+ created_at=datetime.fromisoformat(data["created_at"]) if data.get("created_at") else Undefined(),
41
+ updated_at=datetime.fromisoformat(data["updated_at"]) if data.get("updated_at") else Undefined(),
42
+ custom_data=(
43
+ CustomData(data["custom_data"])
44
+ if isinstance(data.get("custom_data"), dict)
45
+ else data.get("custom_data", Undefined())
46
+ ),
47
+ import_meta=(
48
+ ImportMeta.from_dict(data["import_meta"])
49
+ if isinstance(data.get("import_meta"), dict)
50
+ else data.get("import_meta", Undefined())
51
+ ),
52
+ )
@@ -0,0 +1,68 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from datetime import datetime
4
+
5
+ from paddle_billing.Undefined import Undefined
6
+ from paddle_billing.Notifications.Entities.Adjustments import AdjustmentItem, AdjustmentTaxRatesUsed
7
+ from paddle_billing.Notifications.Entities.Shared import (
8
+ Action,
9
+ AdjustmentActionType,
10
+ AdjustmentStatus,
11
+ CurrencyCode,
12
+ PayoutTotalsAdjustment,
13
+ AdjustmentTotals,
14
+ )
15
+ from paddle_billing.Notifications.Entities.Simulations.SimulationEntity import SimulationEntity
16
+
17
+
18
+ @dataclass
19
+ class Adjustment(SimulationEntity):
20
+ id: str | Undefined = Undefined()
21
+ action: Action | Undefined = Undefined()
22
+ transaction_id: str | Undefined = Undefined()
23
+ subscription_id: str | None | Undefined = Undefined()
24
+ customer_id: str | Undefined = Undefined()
25
+ reason: str | Undefined = Undefined()
26
+ credit_applied_to_balance: bool | None | Undefined = Undefined()
27
+ currency_code: CurrencyCode | Undefined = Undefined()
28
+ status: AdjustmentStatus | Undefined = Undefined()
29
+ items: list[AdjustmentItem] | Undefined = Undefined()
30
+ totals: AdjustmentTotals | Undefined = Undefined()
31
+ payout_totals: PayoutTotalsAdjustment | None | Undefined = Undefined()
32
+ created_at: datetime | Undefined = Undefined()
33
+ updated_at: datetime | None | Undefined = Undefined()
34
+ tax_rates_used: list[AdjustmentTaxRatesUsed] | None | Undefined = Undefined()
35
+ type: AdjustmentActionType | None | Undefined = Undefined()
36
+
37
+ @staticmethod
38
+ def from_dict(data: dict) -> Adjustment:
39
+ return Adjustment(
40
+ id=data.get("id", Undefined()),
41
+ action=Action(data["action"]) if data.get("action") else Undefined(),
42
+ transaction_id=data.get("transaction_id", Undefined()),
43
+ subscription_id=data.get("subscription_id", Undefined()),
44
+ customer_id=data.get("customer_id", Undefined()),
45
+ reason=data.get("reason", Undefined()),
46
+ credit_applied_to_balance=data.get("credit_applied_to_balance", Undefined()),
47
+ currency_code=CurrencyCode(data["currency_code"]) if data.get("currency_code") else Undefined(),
48
+ status=AdjustmentStatus(data["status"]) if data.get("status") else Undefined(),
49
+ totals=AdjustmentTotals.from_dict(data["totals"]) if data.get("totals") else Undefined(),
50
+ created_at=datetime.fromisoformat(data["created_at"]) if data.get("created_at") else Undefined(),
51
+ items=[AdjustmentItem.from_dict(item) for item in data["items"]] if data.get("items") else Undefined(),
52
+ payout_totals=(
53
+ PayoutTotalsAdjustment.from_dict(data["payout_totals"])
54
+ if data.get("payout_totals")
55
+ else data.get("payout_totals", Undefined())
56
+ ),
57
+ updated_at=(
58
+ datetime.fromisoformat(data["updated_at"])
59
+ if data.get("updated_at")
60
+ else data.get("updated_at", Undefined())
61
+ ),
62
+ tax_rates_used=(
63
+ [AdjustmentTaxRatesUsed.from_dict(item) for item in data["tax_rates_used"]]
64
+ if data.get("tax_rates_used")
65
+ else data.get("tax_rates_used", Undefined())
66
+ ),
67
+ type=AdjustmentActionType(data["type"]) if data.get("type") else Undefined(),
68
+ )