python-terminusgps 27.3.1__py3-none-any.whl → 28.0.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.1
3
+ Version: 28.0.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
@@ -7,10 +7,10 @@ terminusgps/authorizenet/utils.py,sha256=RQ_R9YEoNGYQNV7vePmNxbYyhf_DImumATyROck
7
7
  terminusgps/authorizenet/profiles/__init__.py,sha256=QKjMKcXpCSCEhv6LBCz0yGP8t0VxAyKyYRS4_HLYnxQ,114
8
8
  terminusgps/authorizenet/profiles/addresses.py,sha256=7yrOrb9kIsiiazgWbeH8v_YUBiWG3Y61g46R3S5DD-k,6592
9
9
  terminusgps/authorizenet/profiles/base.py,sha256=TOUHr22QRQBLErdysOkfcpJBusTjrUTqOmWEyNvMacA,2240
10
- terminusgps/authorizenet/profiles/customers.py,sha256=xQB0M9Hr1vvtoiBEV2Fp0RELgJ9Mx8kAJ3sFwZif80o,8532
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/subscriptions/__init__.py,sha256=OqRean82wOsuvnV3iadVxJhWt0nvspEvWPOg9sUJ4AA,40
13
+ terminusgps/authorizenet/subscriptions/subscriptions.py,sha256=rZQXbs4wCj9EIuAfywKpE-jYQhfkXxNEvfcaH13YITY,8673
14
14
  terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  terminusgps/aws/secrets.py,sha256=MxQEmmBLpMUQ2tYAsHdCYf-7RZ84LiogdKcTsACX5dw,361
16
16
  terminusgps/twilio/__init__.py,sha256=dYo41F2jft_eHDWSUtSpKGSRG1bewq_qClqilUJZkYM,33
@@ -30,7 +30,7 @@ terminusgps/wialon/items/route.py,sha256=8SzlqNmpYVdt-ZAY--B_KHoDIHgN0Zb7KBsBWAz
30
30
  terminusgps/wialon/items/unit.py,sha256=i7sQiRu3N0XxyTHVN2RnmjYy9X48KdnZLSB18ic37w8,9363
31
31
  terminusgps/wialon/items/unit_group.py,sha256=YsYh34l2DjSKcv5SIZkEVi5FSjveGB1gxU2fwdLyvl4,4101
32
32
  terminusgps/wialon/items/user.py,sha256=PFYBie04F16YE2B5364PLxkmlTmQr4sZXpItvRBxsDc,7143
33
- python_terminusgps-27.3.1.dist-info/METADATA,sha256=5XcDojmOYJL2eB9wIxo6OGhWPFKAONFOC0IJZBE79Bk,946
34
- python_terminusgps-27.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- python_terminusgps-27.3.1.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
36
- python_terminusgps-27.3.1.dist-info/RECORD,,
33
+ python_terminusgps-28.0.0.dist-info/METADATA,sha256=s4YUD2ZeFpd0NvqQFwnOdgfXmdi3ZffXlg3d5D82xhk,946
34
+ python_terminusgps-28.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
+ python_terminusgps-28.0.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
36
+ python_terminusgps-28.0.0.dist-info/RECORD,,
@@ -62,7 +62,7 @@ class CustomerProfile(AuthorizenetProfileBase):
62
62
  int(profile.customerPaymentProfileId)
63
63
  for profile in response.profile.paymentProfiles
64
64
  ]
65
- except ControllerExecutionError:
65
+ except (ControllerExecutionError, AttributeError):
66
66
  return []
67
67
 
68
68
  @property
@@ -74,7 +74,7 @@ class CustomerProfile(AuthorizenetProfileBase):
74
74
  int(profile.customerAddressId)
75
75
  for profile in response.profile.shipToList
76
76
  ]
77
- except ControllerExecutionError:
77
+ except (ControllerExecutionError, AttributeError):
78
78
  return []
79
79
 
80
80
  @property
@@ -0,0 +1 @@
1
+ from .subscriptions import Subscription
@@ -1,3 +1,5 @@
1
+ import decimal
2
+
1
3
  from authorizenet import apicontractsv1, apicontrollers
2
4
 
3
5
  from ..auth import get_merchant_auth
@@ -8,20 +10,55 @@ class Subscription(ControllerExecutionMixin):
8
10
  def __init__(self, id: str | int | None = None, *args, **kwargs) -> None:
9
11
  if id and isinstance(id, str) and not id.isdigit():
10
12
  raise ValueError(f"'id' must be a digit, got '{id}'.")
11
- self.id = int(id if id else self.create(*args, **kwargs))
13
+ self.id = int(id) if id else self.create(*args, **kwargs)
12
14
 
13
15
  def create(
14
16
  self,
15
17
  name: str,
16
- amount: str,
18
+ amount: decimal.Decimal,
17
19
  schedule: apicontractsv1.paymentScheduleType,
18
20
  profile_id: int | str,
19
21
  payment_id: int | str,
20
22
  address_id: int | str,
21
- trial_amount: str = "0.00",
23
+ trial_amount: decimal.Decimal = decimal.Decimal(
24
+ 0.00, context=decimal.Context(prec=2, rounding=decimal.ROUND_HALF_UP)
25
+ ),
22
26
  ) -> int:
27
+ """
28
+ Creates a subscription in Authorizenet.
29
+
30
+ :param name: A name for the subscription.
31
+ :type name: :py:obj:`str`
32
+ :param amount: An amount of money paid per occurrence of the subscription.
33
+ :type amount: :py:obj:`~decimal.Decimal`
34
+ :param schedule: A payment schedule for the subscription.
35
+ :type amount: :py:obj:`~authorizenet.apicontractsv1.paymentScheduleType`
36
+ :param profile_id: An Authoriznet customer profile id.
37
+ :type profile_id: :py:obj:`int` | :py:obj:`str`
38
+ :param payment_id: An Authoriznet customer payment profile id.
39
+ :type payment_id: :py:obj:`int` | :py:obj:`str`
40
+ :param address_id: An Authoriznet customer address profile id.
41
+ :type address_id: :py:obj:`int` | :py:obj:`str`
42
+ :param trial_amount: Trial amount for the subscription. Default is ``0.00``.
43
+ :type trial_amount: :py:obj:`~decimal.Decimal`
44
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
45
+ :raises ValueError: If ``profile_id`` wasn't a digit.
46
+ :raises ValueError: If ``payment_id`` wasn't a digit.
47
+ :raises ValueError: If ``address_id`` wasn't a digit.
48
+ :raises ValueError: If the Authorizenet API response was not retrieved.
49
+ :returns: An Authorizenet subscription id.
50
+ :rtype: :py:obj:`int`
51
+
52
+ """
53
+ if isinstance(profile_id, str) and not profile_id.isdigit():
54
+ raise ValueError(f"'profile_id' must be a digit, got '{profile_id}'.")
55
+ if isinstance(payment_id, str) and not payment_id.isdigit():
56
+ raise ValueError(f"'payment_id' must be a digit, got '{payment_id}'.")
57
+ if isinstance(address_id, str) and not address_id.isdigit():
58
+ raise ValueError(f"'address_id' must be a digit, got '{address_id}'.")
59
+
23
60
  request = apicontractsv1.ARBCreateSubscriptionRequest(
24
- merchantAuthentication=get_merchant_auth(),
61
+ merchantAuthentication=self.merchantAuthentication,
25
62
  subscription=apicontractsv1.ARBSubscriptionType(
26
63
  name=name,
27
64
  paymentSchedule=schedule,
@@ -39,3 +76,120 @@ class Subscription(ControllerExecutionMixin):
39
76
  if response is None:
40
77
  raise ValueError("Failed to retrieve Authorizenet API response.")
41
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
+ @property
93
+ def merchantAuthentication(self) -> apicontractsv1.merchantAuthenticationType:
94
+ """Merchant authentication for API calls."""
95
+ return get_merchant_auth()
96
+
97
+ @property
98
+ def status(self) -> str | None:
99
+ """Current status of the subscription."""
100
+ response: dict | None = self._authorizenet_get_subscription_status()
101
+ return str(response.status) if response else None
102
+
103
+ @property
104
+ def transactions(self) -> list | None:
105
+ """Transactions for the subscription."""
106
+ response = self._authorizenet_get_subscription(include_transactions=True)
107
+ return response.arbTransactions.getchildren() if response else None
108
+
109
+ def _authorizenet_get_subscription(
110
+ self, include_transactions: bool = False
111
+ ) -> dict | None:
112
+ """
113
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBGetSubscriptionRequest` using the Authorizenet API.
114
+
115
+ `ARBGetSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-get-subscription>`_
116
+
117
+ :raises AssertionError: If :py:attr:`id` wasn't set.
118
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
119
+ :returns: An Authorizenet API response, if any.
120
+ :rtype: :py:obj:`dict` | :py:obj:`None`
121
+
122
+ """
123
+ assert self.id, "'id' was not set."
124
+
125
+ request = apicontractsv1.ARBGetSubscriptionRequest(
126
+ merchantAuthentication=self.merchantAuthentication,
127
+ subscriptionId=self.id,
128
+ includeTransactions=str(include_transactions).lower(),
129
+ )
130
+ controller = apicontrollers.ARBGetSubscriptionController(request)
131
+ return self.execute_controller(controller)
132
+
133
+ def _authorizenet_get_subscription_status(self) -> dict | None:
134
+ """
135
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBGetSubscriptionStatusRequest` using the Authorizenet API.
136
+
137
+ `ARBGetSubscriptionStatusRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-get-subscription-status>`_
138
+
139
+ :raises AssertionError: If :py:attr:`id` wasn't set.
140
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
141
+ :returns: An Authorizenet API response, if any.
142
+ :rtype: :py:obj:`dict` | :py:obj:`None`
143
+
144
+ """
145
+ assert self.id, "'id' was not set."
146
+
147
+ request = apicontractsv1.ARBGetSubscriptionStatusRequest(
148
+ merchantAuthentication=self.merchantAuthentication, subscriptionId=self.id
149
+ )
150
+ controller = apicontrollers.ARBGetSubscriptionStatusController(request)
151
+ return self.execute_controller(controller)
152
+
153
+ def _authorizenet_update_subscription(
154
+ self, subscription: apicontractsv1.ARBSubscriptionType
155
+ ) -> dict | None:
156
+ """
157
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBUpdateSubscriptionRequest` using the Authorizenet API.
158
+
159
+ `ARBUpdateSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-update-a-subscription>`_
160
+
161
+ :raises AssertionError: If :py:attr:`id` wasn't set.
162
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
163
+ :returns: An Authorizenet API response, if any.
164
+ :rtype: :py:obj:`dict` | :py:obj:`None`
165
+
166
+ """
167
+ assert self.id, "'id' was not set."
168
+
169
+ request = apicontractsv1.ARBUpdateSubscriptionRequest(
170
+ merchantAuthentication=self.merchantAuthentication,
171
+ subscriptionId=self.id,
172
+ subscription=subscription,
173
+ )
174
+ controller = apicontrollers.ARBUpdateSubscriptionController(request)
175
+ return self.execute_controller(controller)
176
+
177
+ def _authorizenet_cancel_subscription(self) -> dict | None:
178
+ """
179
+ Executes a :py:obj:`~authorizenet.apicontractsv1.ARBCancelSubscriptionRequest` using the Authorizenet API.
180
+
181
+ `ARBCancelSubscriptionRequest <https://developer.authorize.net/api/reference/index.html#recurring-billing-cancel-a-subscription>`_
182
+
183
+ :raises AssertionError: If :py:attr:`id` wasn't set.
184
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
185
+ :returns: An Authorizenet API response, if any.
186
+ :rtype: :py:obj:`dict` | :py:obj:`None`
187
+
188
+ """
189
+ assert self.id, "'id' was not set."
190
+
191
+ request = apicontractsv1.ARBCancelSubscriptionRequest(
192
+ merchantAuthentication=self.merchantAuthentication, subscriptionId=self.id
193
+ )
194
+ controller = apicontrollers.ARBCancelSubscriptionController(request)
195
+ return self.execute_controller(controller)