python-terminusgps 27.3.2__py3-none-any.whl → 28.1.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.

Potentially problematic release.


This version of python-terminusgps might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-terminusgps
3
- Version: 27.3.2
3
+ Version: 28.1.0
4
4
  Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
5
5
  Project-URL: Documentation, https://app.terminusgps.com/docs/apps/python-terminusgps/index.html
6
6
  Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
@@ -4,13 +4,12 @@ terminusgps/authorizenet/__init__.py,sha256=LiGLlWNNiqS7RSOP4Apabx-b9EBYyNbxRY_a
4
4
  terminusgps/authorizenet/auth.py,sha256=ICxPPzoUc64VbsIIemEWKrn8xjHGwbNdo2VbtaFCFss,1107
5
5
  terminusgps/authorizenet/errors.py,sha256=HG5NwVxQCtOYidVl30y49PC0Ovw5VYdsy9wTgUFMw9M,949
6
6
  terminusgps/authorizenet/utils.py,sha256=RQ_R9YEoNGYQNV7vePmNxbYyhf_DImumATyROckX66I,2770
7
- terminusgps/authorizenet/profiles/__init__.py,sha256=QKjMKcXpCSCEhv6LBCz0yGP8t0VxAyKyYRS4_HLYnxQ,114
7
+ terminusgps/authorizenet/profiles/__init__.py,sha256=IG4XCEEYtHKqXOatlZlob6J3ukAgF7cFR-RXxOSMS1c,161
8
8
  terminusgps/authorizenet/profiles/addresses.py,sha256=7yrOrb9kIsiiazgWbeH8v_YUBiWG3Y61g46R3S5DD-k,6592
9
9
  terminusgps/authorizenet/profiles/base.py,sha256=TOUHr22QRQBLErdysOkfcpJBusTjrUTqOmWEyNvMacA,2240
10
10
  terminusgps/authorizenet/profiles/customers.py,sha256=-F8IsQEn2CyHpfxyVZjKayHSuVe4ENNUj_ck7SE8LO0,8568
11
11
  terminusgps/authorizenet/profiles/payments.py,sha256=ohhZrs9MB7GkCi7jQvPVvELNKnR9BwzMd607jJmT4n4,11316
12
- terminusgps/authorizenet/subscriptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- terminusgps/authorizenet/subscriptions/subscriptions.py,sha256=t1yNGMnfVEhSLMerZmEr479XDgOY-ksqvCn3FNcymVE,1609
12
+ terminusgps/authorizenet/profiles/subscriptions.py,sha256=10Jlt19k-4c2GkG7lfKcRnYk0KUKZsSCgxpdDQQ5RHw,12426
14
13
  terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
14
  terminusgps/aws/secrets.py,sha256=MxQEmmBLpMUQ2tYAsHdCYf-7RZ84LiogdKcTsACX5dw,361
16
15
  terminusgps/twilio/__init__.py,sha256=dYo41F2jft_eHDWSUtSpKGSRG1bewq_qClqilUJZkYM,33
@@ -30,7 +29,7 @@ terminusgps/wialon/items/route.py,sha256=8SzlqNmpYVdt-ZAY--B_KHoDIHgN0Zb7KBsBWAz
30
29
  terminusgps/wialon/items/unit.py,sha256=i7sQiRu3N0XxyTHVN2RnmjYy9X48KdnZLSB18ic37w8,9363
31
30
  terminusgps/wialon/items/unit_group.py,sha256=YsYh34l2DjSKcv5SIZkEVi5FSjveGB1gxU2fwdLyvl4,4101
32
31
  terminusgps/wialon/items/user.py,sha256=PFYBie04F16YE2B5364PLxkmlTmQr4sZXpItvRBxsDc,7143
33
- python_terminusgps-27.3.2.dist-info/METADATA,sha256=yrW36bhrccaYkwU8d1LfDfbEF0wZoW2BdP3IRpu78dI,946
34
- python_terminusgps-27.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- python_terminusgps-27.3.2.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
36
- python_terminusgps-27.3.2.dist-info/RECORD,,
32
+ python_terminusgps-28.1.0.dist-info/METADATA,sha256=kEqWCNoPiDseRB3diJNYEnRlLq1cLagusBQTkPtezHc,946
33
+ python_terminusgps-28.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
+ python_terminusgps-28.1.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
35
+ python_terminusgps-28.1.0.dist-info/RECORD,,
@@ -1,3 +1,4 @@
1
1
  from .addresses import AddressProfile
2
2
  from .customers import CustomerProfile
3
3
  from .payments import PaymentProfile
4
+ from .subscriptions import SubscriptionProfile
@@ -0,0 +1,276 @@
1
+ import decimal
2
+
3
+ from authorizenet import apicontractsv1, apicontrollers
4
+
5
+ from ..auth import get_merchant_auth
6
+ from ..utils import ControllerExecutionMixin
7
+
8
+
9
+ class SubscriptionProfile(ControllerExecutionMixin):
10
+ """An Authorizenet subscription profile."""
11
+
12
+ def __init__(self, id: str | int | None = None, *args, **kwargs) -> None:
13
+ if id and isinstance(id, str) and not id.isdigit():
14
+ raise ValueError(f"'id' must be a digit, got '{id}'.")
15
+ self.id = int(id) if id else self.create(*args, **kwargs)
16
+
17
+ def create(
18
+ self,
19
+ name: str,
20
+ amount: decimal.Decimal,
21
+ schedule: apicontractsv1.paymentScheduleType,
22
+ profile_id: int | str,
23
+ payment_id: int | str,
24
+ address_id: int | str,
25
+ trial_amount: decimal.Decimal = decimal.Decimal(
26
+ 0.00, context=decimal.Context(prec=2, rounding=decimal.ROUND_HALF_UP)
27
+ ),
28
+ ) -> int:
29
+ """
30
+ Creates a subscription in Authorizenet.
31
+
32
+ :param name: A name for the subscription.
33
+ :type name: :py:obj:`str`
34
+ :param amount: An amount of money paid per occurrence of the subscription.
35
+ :type amount: :py:obj:`~decimal.Decimal`
36
+ :param schedule: A payment schedule for the subscription.
37
+ :type amount: :py:obj:`~authorizenet.apicontractsv1.paymentScheduleType`
38
+ :param profile_id: An Authoriznet customer profile id.
39
+ :type profile_id: :py:obj:`int` | :py:obj:`str`
40
+ :param payment_id: An Authoriznet customer payment profile id.
41
+ :type payment_id: :py:obj:`int` | :py:obj:`str`
42
+ :param address_id: An Authoriznet customer address profile id.
43
+ :type address_id: :py:obj:`int` | :py:obj:`str`
44
+ :param trial_amount: Trial amount for the subscription. Default is ``0.00``.
45
+ :type trial_amount: :py:obj:`~decimal.Decimal`
46
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
47
+ :raises ValueError: If ``profile_id`` wasn't a digit.
48
+ :raises ValueError: If ``payment_id`` wasn't a digit.
49
+ :raises ValueError: If ``address_id`` wasn't a digit.
50
+ :raises ValueError: If the Authorizenet API response was not retrieved.
51
+ :returns: An Authorizenet subscription id.
52
+ :rtype: :py:obj:`int`
53
+
54
+ """
55
+ if isinstance(profile_id, str) and not profile_id.isdigit():
56
+ raise ValueError(f"'profile_id' must be a digit, got '{profile_id}'.")
57
+ if isinstance(payment_id, str) and not payment_id.isdigit():
58
+ raise ValueError(f"'payment_id' must be a digit, got '{payment_id}'.")
59
+ if isinstance(address_id, str) and not address_id.isdigit():
60
+ raise ValueError(f"'address_id' must be a digit, got '{address_id}'.")
61
+
62
+ subscription: apicontractsv1.ARBSubscriptionType = (
63
+ apicontractsv1.ARBSubscriptionType(
64
+ name=name,
65
+ paymentSchedule=schedule,
66
+ amount=amount,
67
+ trialAmount=trial_amount,
68
+ profile=apicontractsv1.customerProfileIdType(
69
+ customerProfileId=str(profile_id),
70
+ customerPaymentProfileId=str(payment_id),
71
+ customerAddressId=str(address_id),
72
+ ),
73
+ )
74
+ )
75
+ response = self._authorizenet_create_subscription(subscription)
76
+ if response is None:
77
+ raise ValueError("Failed to retrieve Authorizenet API response.")
78
+ return int(response.subscriptionId)
79
+
80
+ def cancel(self) -> None:
81
+ """
82
+ Cancels the subscription.
83
+
84
+ :raises AssertionError: If :py:attr:`id` wasn't set.
85
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
86
+ :returns: Nothing.
87
+ :rtype: :py:obj:`None`
88
+
89
+ """
90
+ self._authorizenet_cancel_subscription()
91
+
92
+ def update(
93
+ self,
94
+ name: str,
95
+ amount: decimal.Decimal,
96
+ schedule: apicontractsv1.paymentScheduleType,
97
+ profile_id: int | str,
98
+ payment_id: int | str,
99
+ address_id: int | str,
100
+ trial_amount: decimal.Decimal = decimal.Decimal(
101
+ 0.00, context=decimal.Context(prec=2, rounding=decimal.ROUND_HALF_UP)
102
+ ),
103
+ ) -> None:
104
+ """
105
+ Updates a subscription in Authorizenet.
106
+
107
+ :param name: A name for the subscription.
108
+ :type name: :py:obj:`str`
109
+ :param amount: An amount of money paid per occurrence of the subscription.
110
+ :type amount: :py:obj:`~decimal.Decimal`
111
+ :param schedule: A payment schedule for the subscription.
112
+ :type amount: :py:obj:`~authorizenet.apicontractsv1.paymentScheduleType`
113
+ :param profile_id: An Authoriznet customer profile id.
114
+ :type profile_id: :py:obj:`int` | :py:obj:`str`
115
+ :param payment_id: An Authoriznet customer payment profile id.
116
+ :type payment_id: :py:obj:`int` | :py:obj:`str`
117
+ :param address_id: An Authoriznet customer address profile id.
118
+ :type address_id: :py:obj:`int` | :py:obj:`str`
119
+ :param trial_amount: Trial amount for the subscription. Default is ``0.00``.
120
+ :type trial_amount: :py:obj:`~decimal.Decimal`
121
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
122
+ :raises ValueError: If ``profile_id`` wasn't a digit.
123
+ :raises ValueError: If ``payment_id`` wasn't a digit.
124
+ :raises ValueError: If ``address_id`` wasn't a digit.
125
+ :raises ValueError: If the Authorizenet API response was not retrieved.
126
+ :returns: An Authorizenet subscription id.
127
+ :rtype: :py:obj:`int`
128
+
129
+ """
130
+ if isinstance(profile_id, str) and not profile_id.isdigit():
131
+ raise ValueError(f"'profile_id' must be a digit, got '{profile_id}'.")
132
+ if isinstance(payment_id, str) and not payment_id.isdigit():
133
+ raise ValueError(f"'payment_id' must be a digit, got '{payment_id}'.")
134
+ if isinstance(address_id, str) and not address_id.isdigit():
135
+ raise ValueError(f"'address_id' must be a digit, got '{address_id}'.")
136
+
137
+ subscription: apicontractsv1.ARBSubscriptionType = (
138
+ apicontractsv1.ARBSubscriptionType(
139
+ name=name,
140
+ paymentSchedule=schedule,
141
+ amount=amount,
142
+ trialAmount=trial_amount,
143
+ profile=apicontractsv1.customerProfileIdType(
144
+ customerProfileId=str(profile_id),
145
+ customerPaymentProfileId=str(payment_id),
146
+ customerAddressId=str(address_id),
147
+ ),
148
+ )
149
+ )
150
+ self._authorizenet_update_subscription(subscription)
151
+
152
+ @property
153
+ def merchantAuthentication(self) -> apicontractsv1.merchantAuthenticationType:
154
+ """Merchant authentication for API calls."""
155
+ return get_merchant_auth()
156
+
157
+ @property
158
+ def status(self) -> str | None:
159
+ """Current status of the subscription."""
160
+ response: dict | None = self._authorizenet_get_subscription_status()
161
+ return str(response.status) if response else None
162
+
163
+ @property
164
+ def transactions(self) -> list | None:
165
+ """Transactions for the subscription."""
166
+ response = self._authorizenet_get_subscription(include_transactions=True)
167
+ return response.arbTransactions.getchildren() if response else None
168
+
169
+ def _authorizenet_create_subscription(
170
+ self, subscription: apicontractsv1.ARBSubscriptionType
171
+ ) -> dict | None:
172
+ """
173
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBCreateSubscriptionRequest` using the Authorizenet API.
174
+
175
+ `ARBCreateSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-create-a-subscription-from-customer-profile>`_
176
+
177
+ :raises AssertionError: If :py:attr:`id` wasn't set.
178
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
179
+ :returns: An Authorizenet API response, if any.
180
+ :rtype: :py:obj:`dict` | :py:obj:`None`
181
+
182
+ """
183
+ request = apicontractsv1.ARBCreateSubscriptionRequest(
184
+ merchantAuthentication=self.merchantAuthentication,
185
+ subscription=subscription,
186
+ )
187
+ controller = apicontrollers.ARBCreateSubscriptionController(request)
188
+ return self.execute_controller(controller)
189
+
190
+ def _authorizenet_get_subscription(
191
+ self, include_transactions: bool = False
192
+ ) -> dict | None:
193
+ """
194
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBGetSubscriptionRequest` using the Authorizenet API.
195
+
196
+ `ARBGetSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-get-subscription>`_
197
+
198
+ :raises AssertionError: If :py:attr:`id` wasn't set.
199
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
200
+ :returns: An Authorizenet API response, if any.
201
+ :rtype: :py:obj:`dict` | :py:obj:`None`
202
+
203
+ """
204
+ assert self.id, "'id' was not set."
205
+
206
+ request = apicontractsv1.ARBGetSubscriptionRequest(
207
+ merchantAuthentication=self.merchantAuthentication,
208
+ subscriptionId=self.id,
209
+ includeTransactions=str(include_transactions).lower(),
210
+ )
211
+ controller = apicontrollers.ARBGetSubscriptionController(request)
212
+ return self.execute_controller(controller)
213
+
214
+ def _authorizenet_get_subscription_status(self) -> dict | None:
215
+ """
216
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBGetSubscriptionStatusRequest` using the Authorizenet API.
217
+
218
+ `ARBGetSubscriptionStatusRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-get-subscription-status>`_
219
+
220
+ :raises AssertionError: If :py:attr:`id` wasn't set.
221
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
222
+ :returns: An Authorizenet API response, if any.
223
+ :rtype: :py:obj:`dict` | :py:obj:`None`
224
+
225
+ """
226
+ assert self.id, "'id' was not set."
227
+
228
+ request = apicontractsv1.ARBGetSubscriptionStatusRequest(
229
+ merchantAuthentication=self.merchantAuthentication, subscriptionId=self.id
230
+ )
231
+ controller = apicontrollers.ARBGetSubscriptionStatusController(request)
232
+ return self.execute_controller(controller)
233
+
234
+ def _authorizenet_update_subscription(
235
+ self, subscription: apicontractsv1.ARBSubscriptionType
236
+ ) -> dict | None:
237
+ """
238
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBUpdateSubscriptionRequest` using the Authorizenet API.
239
+
240
+ `ARBUpdateSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-update-a-subscription>`_
241
+
242
+ :raises AssertionError: If :py:attr:`id` wasn't set.
243
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
244
+ :returns: An Authorizenet API response, if any.
245
+ :rtype: :py:obj:`dict` | :py:obj:`None`
246
+
247
+ """
248
+ assert self.id, "'id' was not set."
249
+
250
+ request = apicontractsv1.ARBUpdateSubscriptionRequest(
251
+ merchantAuthentication=self.merchantAuthentication,
252
+ subscriptionId=self.id,
253
+ subscription=subscription,
254
+ )
255
+ controller = apicontrollers.ARBUpdateSubscriptionController(request)
256
+ return self.execute_controller(controller)
257
+
258
+ def _authorizenet_cancel_subscription(self) -> dict | None:
259
+ """
260
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBCancelSubscriptionRequest` using the Authorizenet API.
261
+
262
+ `ARBCancelSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-cancel-a-subscription>`_
263
+
264
+ :raises AssertionError: If :py:attr:`id` wasn't set.
265
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
266
+ :returns: An Authorizenet API response, if any.
267
+ :rtype: :py:obj:`dict` | :py:obj:`None`
268
+
269
+ """
270
+ assert self.id, "'id' was not set."
271
+
272
+ request = apicontractsv1.ARBCancelSubscriptionRequest(
273
+ merchantAuthentication=self.merchantAuthentication, subscriptionId=self.id
274
+ )
275
+ controller = apicontrollers.ARBCancelSubscriptionController(request)
276
+ return self.execute_controller(controller)
File without changes
@@ -1,41 +0,0 @@
1
- from authorizenet import apicontractsv1, apicontrollers
2
-
3
- from ..auth import get_merchant_auth
4
- from ..utils import ControllerExecutionMixin
5
-
6
-
7
- class Subscription(ControllerExecutionMixin):
8
- def __init__(self, id: str | int | None = None, *args, **kwargs) -> None:
9
- if id and isinstance(id, str) and not id.isdigit():
10
- raise ValueError(f"'id' must be a digit, got '{id}'.")
11
- self.id = int(id if id else self.create(*args, **kwargs))
12
-
13
- def create(
14
- self,
15
- name: str,
16
- amount: str,
17
- schedule: apicontractsv1.paymentScheduleType,
18
- profile_id: int | str,
19
- payment_id: int | str,
20
- address_id: int | str,
21
- trial_amount: str = "0.00",
22
- ) -> int:
23
- request = apicontractsv1.ARBCreateSubscriptionRequest(
24
- merchantAuthentication=get_merchant_auth(),
25
- subscription=apicontractsv1.ARBSubscriptionType(
26
- name=name,
27
- paymentSchedule=schedule,
28
- amount=amount,
29
- trialAmount=trial_amount,
30
- profile=apicontractsv1.customerProfileIdType(
31
- customerProfileId=str(profile_id),
32
- customerPaymentProfileId=str(payment_id),
33
- customerAddressId=str(address_id),
34
- ),
35
- ),
36
- )
37
- controller = apicontrollers.ARBCreateSubscriptionController(request)
38
- response = self.execute_controller(controller)
39
- if response is None:
40
- raise ValueError("Failed to retrieve Authorizenet API response.")
41
- return int(response.subscriptionId)