ordercloud-python 2026.4.1__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 (114) hide show
  1. ordercloud/__init__.py +37 -0
  2. ordercloud/auth.py +136 -0
  3. ordercloud/client.py +211 -0
  4. ordercloud/config.py +42 -0
  5. ordercloud/errors.py +47 -0
  6. ordercloud/http.py +218 -0
  7. ordercloud/middleware.py +66 -0
  8. ordercloud/models/__init__.py +271 -0
  9. ordercloud/models/address.py +47 -0
  10. ordercloud/models/api_client.py +116 -0
  11. ordercloud/models/approval.py +73 -0
  12. ordercloud/models/assignments.py +402 -0
  13. ordercloud/models/auth_models.py +114 -0
  14. ordercloud/models/bundle.py +31 -0
  15. ordercloud/models/buyer.py +271 -0
  16. ordercloud/models/catalog.py +33 -0
  17. ordercloud/models/category.py +35 -0
  18. ordercloud/models/cost_center.py +27 -0
  19. ordercloud/models/credit_card.py +35 -0
  20. ordercloud/models/delivery.py +277 -0
  21. ordercloud/models/discount.py +63 -0
  22. ordercloud/models/integration.py +76 -0
  23. ordercloud/models/inventory_record.py +53 -0
  24. ordercloud/models/line_item.py +95 -0
  25. ordercloud/models/line_item_types.py +89 -0
  26. ordercloud/models/message_sender.py +80 -0
  27. ordercloud/models/misc.py +280 -0
  28. ordercloud/models/open_id_connect.py +47 -0
  29. ordercloud/models/order.py +477 -0
  30. ordercloud/models/order_return.py +92 -0
  31. ordercloud/models/payment.py +77 -0
  32. ordercloud/models/price_schedule.py +76 -0
  33. ordercloud/models/product.py +227 -0
  34. ordercloud/models/product_collection.py +186 -0
  35. ordercloud/models/promotion.py +297 -0
  36. ordercloud/models/security.py +89 -0
  37. ordercloud/models/shared.py +131 -0
  38. ordercloud/models/shipment.py +150 -0
  39. ordercloud/models/spec.py +67 -0
  40. ordercloud/models/spending_account.py +33 -0
  41. ordercloud/models/subscription.py +125 -0
  42. ordercloud/models/supplier.py +43 -0
  43. ordercloud/models/sync.py +172 -0
  44. ordercloud/models/user.py +207 -0
  45. ordercloud/models/user_group.py +27 -0
  46. ordercloud/models/webhook.py +58 -0
  47. ordercloud/py.typed +0 -0
  48. ordercloud/resources/__init__.py +65 -0
  49. ordercloud/resources/addresses.py +228 -0
  50. ordercloud/resources/admin_addresses.py +128 -0
  51. ordercloud/resources/admin_user_groups.py +185 -0
  52. ordercloud/resources/admin_users.py +150 -0
  53. ordercloud/resources/api_clients.py +308 -0
  54. ordercloud/resources/approval_rules.py +144 -0
  55. ordercloud/resources/base.py +145 -0
  56. ordercloud/resources/bundle_line_items.py +59 -0
  57. ordercloud/resources/bundle_subscription_items.py +54 -0
  58. ordercloud/resources/bundles.py +278 -0
  59. ordercloud/resources/buyer_groups.py +128 -0
  60. ordercloud/resources/buyers.py +164 -0
  61. ordercloud/resources/cart.py +613 -0
  62. ordercloud/resources/catalogs.py +311 -0
  63. ordercloud/resources/categories.py +392 -0
  64. ordercloud/resources/cost_centers.py +222 -0
  65. ordercloud/resources/credit_cards.py +227 -0
  66. ordercloud/resources/delivery_configurations.py +132 -0
  67. ordercloud/resources/discounts.py +201 -0
  68. ordercloud/resources/entity_syncs.py +534 -0
  69. ordercloud/resources/error_configs.py +71 -0
  70. ordercloud/resources/forgotten_credentials.py +74 -0
  71. ordercloud/resources/group_orders.py +28 -0
  72. ordercloud/resources/impersonation_configs.py +132 -0
  73. ordercloud/resources/incrementors.py +128 -0
  74. ordercloud/resources/integration_events.py +203 -0
  75. ordercloud/resources/inventory_integrations.py +65 -0
  76. ordercloud/resources/inventory_records.py +484 -0
  77. ordercloud/resources/line_items.py +262 -0
  78. ordercloud/resources/locales.py +203 -0
  79. ordercloud/resources/me.py +1882 -0
  80. ordercloud/resources/message_senders.py +261 -0
  81. ordercloud/resources/open_id_connects.py +128 -0
  82. ordercloud/resources/order_returns.py +306 -0
  83. ordercloud/resources/order_syncs.py +65 -0
  84. ordercloud/resources/orders.py +689 -0
  85. ordercloud/resources/payments.py +176 -0
  86. ordercloud/resources/price_schedules.py +164 -0
  87. ordercloud/resources/product_collections.py +116 -0
  88. ordercloud/resources/product_facets.py +128 -0
  89. ordercloud/resources/product_syncs.py +76 -0
  90. ordercloud/resources/products.py +454 -0
  91. ordercloud/resources/promotion_integrations.py +65 -0
  92. ordercloud/resources/promotions.py +203 -0
  93. ordercloud/resources/security_profiles.py +222 -0
  94. ordercloud/resources/seller_approval_rules.py +128 -0
  95. ordercloud/resources/shipments.py +256 -0
  96. ordercloud/resources/specs.py +313 -0
  97. ordercloud/resources/spending_accounts.py +227 -0
  98. ordercloud/resources/subscription_integrations.py +65 -0
  99. ordercloud/resources/subscription_items.py +146 -0
  100. ordercloud/resources/subscriptions.py +128 -0
  101. ordercloud/resources/supplier_addresses.py +144 -0
  102. ordercloud/resources/supplier_user_groups.py +210 -0
  103. ordercloud/resources/supplier_users.py +170 -0
  104. ordercloud/resources/suppliers.py +190 -0
  105. ordercloud/resources/tracking_events.py +130 -0
  106. ordercloud/resources/user_groups.py +210 -0
  107. ordercloud/resources/users.py +254 -0
  108. ordercloud/resources/webhooks.py +128 -0
  109. ordercloud/resources/xp_indices.py +77 -0
  110. ordercloud/sync_client.py +170 -0
  111. ordercloud_python-2026.4.1.dist-info/METADATA +552 -0
  112. ordercloud_python-2026.4.1.dist-info/RECORD +114 -0
  113. ordercloud_python-2026.4.1.dist-info/WHEEL +4 -0
  114. ordercloud_python-2026.4.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,150 @@
1
+ # GENERATED by tools/codegen — DO NOT EDIT
2
+ # Source: ordercloud-openapi-v3.json
3
+ """OrderCloud AdminUsers API resource."""
4
+
5
+ from __future__ import annotations
6
+ from typing import Any, Optional, Union
7
+
8
+ from ..models.user import User
9
+ from ..models.shared import ListPage
10
+ from .base import BaseResource
11
+
12
+ __all__ = ["AdminUsersResource"]
13
+
14
+
15
+ class AdminUsersResource(BaseResource):
16
+ """Operations on OrderCloud AdminUsers."""
17
+
18
+ async def list(
19
+ self,
20
+ *,
21
+ search: Optional[str] = None,
22
+ search_on: Optional[str] = None,
23
+ sort_by: Optional[str] = None,
24
+ page: Optional[int] = None,
25
+ page_size: Optional[int] = None,
26
+ filters: Optional[dict[str, Any]] = None,
27
+ ) -> ListPage[User]:
28
+ """List admin users
29
+
30
+ Args:
31
+ search: Word or phrase to search for.
32
+ search_on: Comma-delimited list of fields to search on.
33
+ sort_by: Comma-delimited list of fields to sort by.
34
+ page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
35
+ page_size: Number of results to return per page.
36
+ filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
37
+
38
+ Returns:
39
+ A paginated list of User objects.
40
+ """
41
+ params = self._build_list_params(
42
+ search=search,
43
+ search_on=search_on,
44
+ sort_by=sort_by,
45
+ page=page,
46
+ page_size=page_size,
47
+ filters=filters,
48
+ )
49
+ resp = await self._http.get("/adminusers", **params)
50
+ return self._parse_list(resp.json(), User)
51
+
52
+ async def create(
53
+ self,
54
+ user: Union[User, dict[str, Any]],
55
+ ) -> User:
56
+ """Create an admin user
57
+
58
+ Args:
59
+ user: A ``User`` model or dict. Required fields: Username, FirstName, LastName, Email, Active.
60
+
61
+ Returns:
62
+ The User object.
63
+ """
64
+ resp = await self._http.post("/adminusers", json=self._serialize(user))
65
+ return User(**resp.json())
66
+
67
+ async def get(
68
+ self,
69
+ user_id: str,
70
+ ) -> User:
71
+ """Retrieve an admin user
72
+
73
+ Args:
74
+ user_id: ID of the user.
75
+
76
+ Returns:
77
+ The User object.
78
+ """
79
+ resp = await self._http.get(f"/adminusers/{user_id}")
80
+ return User(**resp.json())
81
+
82
+ async def save(
83
+ self,
84
+ user_id: str,
85
+ user: Union[User, dict[str, Any]],
86
+ ) -> User:
87
+ """Create or update an admin user
88
+
89
+ Args:
90
+ user_id: ID of the user.
91
+ user: A ``User`` model or dict. Required fields: Username, FirstName, LastName, Email, Active.
92
+
93
+ Returns:
94
+ The User object.
95
+ """
96
+ resp = await self._http.put(
97
+ f"/adminusers/{user_id}",
98
+ json=self._serialize(user),
99
+ )
100
+ return User(**resp.json())
101
+
102
+ async def delete(
103
+ self,
104
+ user_id: str,
105
+ ) -> None:
106
+ """Delete an admin user
107
+
108
+ Args:
109
+ user_id: ID of the user.
110
+ """
111
+ await self._http.delete(f"/adminusers/{user_id}")
112
+
113
+ async def patch(
114
+ self,
115
+ user_id: str,
116
+ partial: dict[str, Any],
117
+ ) -> User:
118
+ """Partially update an admin user
119
+
120
+ Args:
121
+ user_id: ID of the user.
122
+ partial: A dict of fields to update.
123
+
124
+ Returns:
125
+ The User object.
126
+ """
127
+ resp = await self._http.patch(f"/adminusers/{user_id}", json=partial)
128
+ return User(**resp.json())
129
+
130
+ async def revoke_user_tokens(
131
+ self,
132
+ user_id: str,
133
+ ) -> None:
134
+ """Revoke a user tokens
135
+
136
+ Args:
137
+ user_id: ID of the user.
138
+ """
139
+ await self._http.delete(f"/adminusers/{user_id}/tokens")
140
+
141
+ async def unlock_user_account(
142
+ self,
143
+ user_id: str,
144
+ ) -> None:
145
+ """Unlock a user account
146
+
147
+ Args:
148
+ user_id: ID of the user.
149
+ """
150
+ await self._http.post(f"/adminusers/{user_id}/unlock")
@@ -0,0 +1,308 @@
1
+ # GENERATED by tools/codegen — DO NOT EDIT
2
+ # Source: ordercloud-openapi-v3.json
3
+ """OrderCloud ApiClients API resource."""
4
+
5
+ from __future__ import annotations
6
+ from typing import Any, Optional, Union
7
+
8
+ from ..models.api_client import ApiClient, ApiClientSecret, ApiClientSecretCreateResponse
9
+ from ..models.assignments import ApiClientAssignment
10
+ from ..models.shared import ListPage
11
+ from .base import BaseResource
12
+
13
+ __all__ = ["ApiClientsResource"]
14
+
15
+
16
+ class ApiClientsResource(BaseResource):
17
+ """Operations on OrderCloud ApiClients."""
18
+
19
+ async def list(
20
+ self,
21
+ *,
22
+ search: Optional[str] = None,
23
+ search_on: Optional[str] = None,
24
+ sort_by: Optional[str] = None,
25
+ page: Optional[int] = None,
26
+ page_size: Optional[int] = None,
27
+ filters: Optional[dict[str, Any]] = None,
28
+ ) -> ListPage[ApiClient]:
29
+ """List API clients
30
+
31
+ Args:
32
+ search: Word or phrase to search for.
33
+ search_on: Comma-delimited list of fields to search on.
34
+ sort_by: Comma-delimited list of fields to sort by.
35
+ page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
36
+ page_size: Number of results to return per page.
37
+ filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
38
+
39
+ Returns:
40
+ A paginated list of ApiClient objects.
41
+ """
42
+ params = self._build_list_params(
43
+ search=search,
44
+ search_on=search_on,
45
+ sort_by=sort_by,
46
+ page=page,
47
+ page_size=page_size,
48
+ filters=filters,
49
+ )
50
+ resp = await self._http.get("/apiclients", **params)
51
+ return self._parse_list(resp.json(), ApiClient)
52
+
53
+ async def create(
54
+ self,
55
+ api_client: Union[ApiClient, dict[str, Any]],
56
+ ) -> ApiClient:
57
+ """Create an API client
58
+
59
+ Args:
60
+ api_client: A ``ApiClient`` model or dict. Required fields: AccessTokenDuration, AppName.
61
+
62
+ Returns:
63
+ The ApiClient object.
64
+ """
65
+ resp = await self._http.post("/apiclients", json=self._serialize(api_client))
66
+ return ApiClient(**resp.json())
67
+
68
+ async def get(
69
+ self,
70
+ api_client_id: str,
71
+ ) -> ApiClient:
72
+ """Retrieve an API client
73
+
74
+ Args:
75
+ api_client_id: ID of the api client.
76
+
77
+ Returns:
78
+ The ApiClient object.
79
+ """
80
+ resp = await self._http.get(f"/apiclients/{api_client_id}")
81
+ return ApiClient(**resp.json())
82
+
83
+ async def save(
84
+ self,
85
+ api_client_id: str,
86
+ api_client: Union[ApiClient, dict[str, Any]],
87
+ ) -> ApiClient:
88
+ """Create or update an API client
89
+
90
+ Args:
91
+ api_client_id: ID of the api client.
92
+ api_client: A ``ApiClient`` model or dict. Required fields: AccessTokenDuration, AppName.
93
+
94
+ Returns:
95
+ The ApiClient object.
96
+ """
97
+ resp = await self._http.put(
98
+ f"/apiclients/{api_client_id}",
99
+ json=self._serialize(api_client),
100
+ )
101
+ return ApiClient(**resp.json())
102
+
103
+ async def delete(
104
+ self,
105
+ api_client_id: str,
106
+ ) -> None:
107
+ """Delete an API client
108
+
109
+ Args:
110
+ api_client_id: ID of the api client.
111
+ """
112
+ await self._http.delete(f"/apiclients/{api_client_id}")
113
+
114
+ async def patch(
115
+ self,
116
+ api_client_id: str,
117
+ partial: dict[str, Any],
118
+ ) -> ApiClient:
119
+ """Partially update an API client
120
+
121
+ Args:
122
+ api_client_id: ID of the api client.
123
+ partial: A dict of fields to update.
124
+
125
+ Returns:
126
+ The ApiClient object.
127
+ """
128
+ resp = await self._http.patch(f"/apiclients/{api_client_id}", json=partial)
129
+ return ApiClient(**resp.json())
130
+
131
+ async def list_secrets(
132
+ self,
133
+ api_client_id: str,
134
+ *,
135
+ search: Optional[str] = None,
136
+ search_on: Optional[str] = None,
137
+ sort_by: Optional[str] = None,
138
+ page: Optional[int] = None,
139
+ page_size: Optional[int] = None,
140
+ filters: Optional[dict[str, Any]] = None,
141
+ ) -> ListPage[ApiClientSecret]:
142
+ """List API client secrets
143
+
144
+ Args:
145
+ api_client_id: ID of the api client.
146
+ search: Word or phrase to search for.
147
+ search_on: Comma-delimited list of fields to search on.
148
+ sort_by: Comma-delimited list of fields to sort by.
149
+ page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
150
+ page_size: Number of results to return per page.
151
+ filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
152
+
153
+ Returns:
154
+ A paginated list of ApiClientSecret objects.
155
+ """
156
+ params = self._build_list_params(
157
+ search=search,
158
+ search_on=search_on,
159
+ sort_by=sort_by,
160
+ page=page,
161
+ page_size=page_size,
162
+ filters=filters,
163
+ )
164
+ resp = await self._http.get(f"/apiclients/{api_client_id}/secrets", **params)
165
+ return self._parse_list(resp.json(), ApiClientSecret)
166
+
167
+ async def create_secret(
168
+ self,
169
+ api_client_id: str,
170
+ api_client_secret: Union[ApiClientSecret, dict[str, Any]],
171
+ ) -> ApiClientSecretCreateResponse:
172
+ """Create an API client secret
173
+
174
+ Args:
175
+ api_client_id: ID of the api client.
176
+ api_client_secret: A ``ApiClientSecret`` model or dict. Required fields: Name.
177
+
178
+ Returns:
179
+ The ApiClientSecretCreateResponse object.
180
+ """
181
+ resp = await self._http.post(
182
+ f"/apiclients/{api_client_id}/secrets", json=self._serialize(api_client_secret)
183
+ )
184
+ return ApiClientSecretCreateResponse(**resp.json())
185
+
186
+ async def get_secret(
187
+ self,
188
+ api_client_id: str,
189
+ api_client_secret_id: str,
190
+ ) -> ApiClientSecret:
191
+ """Retrieve an API client secret
192
+
193
+ Args:
194
+ api_client_id: ID of the api client.
195
+ api_client_secret_id: ID of the api client secret.
196
+
197
+ Returns:
198
+ The ApiClientSecret object.
199
+ """
200
+ resp = await self._http.get(f"/apiclients/{api_client_id}/secrets/{api_client_secret_id}")
201
+ return ApiClientSecret(**resp.json())
202
+
203
+ async def delete_secret(
204
+ self,
205
+ api_client_id: str,
206
+ api_client_secret_id: str,
207
+ ) -> None:
208
+ """Delete an API client secret
209
+
210
+ Args:
211
+ api_client_id: ID of the api client.
212
+ api_client_secret_id: ID of the api client secret.
213
+ """
214
+ await self._http.delete(f"/apiclients/{api_client_id}/secrets/{api_client_secret_id}")
215
+
216
+ async def patch_secret(
217
+ self,
218
+ api_client_id: str,
219
+ api_client_secret_id: str,
220
+ partial: dict[str, Any],
221
+ ) -> ApiClientSecret:
222
+ """Partially update an API client secret
223
+
224
+ Args:
225
+ api_client_id: ID of the api client.
226
+ api_client_secret_id: ID of the api client secret.
227
+ partial: A dict of fields to update.
228
+
229
+ Returns:
230
+ The ApiClientSecret object.
231
+ """
232
+ resp = await self._http.patch(
233
+ f"/apiclients/{api_client_id}/secrets/{api_client_secret_id}", json=partial
234
+ )
235
+ return ApiClientSecret(**resp.json())
236
+
237
+ async def list_assignments(
238
+ self,
239
+ *,
240
+ api_client_id: Optional[str] = None,
241
+ buyer_id: Optional[str] = None,
242
+ supplier_id: Optional[str] = None,
243
+ page: Optional[int] = None,
244
+ page_size: Optional[int] = None,
245
+ ) -> ListPage[ApiClientAssignment]:
246
+ """List API client assignments
247
+
248
+ Args:
249
+ api_client_id: ID of the api client.
250
+ buyer_id: ID of the buyer.
251
+ supplier_id: ID of the supplier.
252
+ page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
253
+ page_size: Number of results to return per page.
254
+
255
+ Returns:
256
+ A paginated list of ApiClientAssignment objects.
257
+ """
258
+ params = self._build_list_params(
259
+ page=page,
260
+ page_size=page_size,
261
+ )
262
+ if api_client_id is not None:
263
+ params["apiClientID"] = api_client_id
264
+ if buyer_id is not None:
265
+ params["buyerID"] = buyer_id
266
+ if supplier_id is not None:
267
+ params["supplierID"] = supplier_id
268
+ resp = await self._http.get("/apiclients/assignments", **params)
269
+ return self._parse_list(resp.json(), ApiClientAssignment)
270
+
271
+ async def save_assignment(
272
+ self,
273
+ api_client_assignment: Union[ApiClientAssignment, dict[str, Any]],
274
+ ) -> None:
275
+ """Create or update an API client assignment
276
+
277
+ Args:
278
+ api_client_assignment: A ``ApiClientAssignment`` model or dict. Required fields: ApiClientID.
279
+ """
280
+ await self._http.post(
281
+ "/apiclients/assignments", json=self._serialize(api_client_assignment)
282
+ )
283
+
284
+ async def delete_buyer_assignment(
285
+ self,
286
+ api_client_id: str,
287
+ buyer_id: str,
288
+ ) -> None:
289
+ """Delete an API client buyer assignment
290
+
291
+ Args:
292
+ api_client_id: ID of the api client.
293
+ buyer_id: ID of the buyer.
294
+ """
295
+ await self._http.delete(f"/buyers/{buyer_id}/ApiClients/Assignments/{api_client_id}")
296
+
297
+ async def delete_supplier_assignment(
298
+ self,
299
+ api_client_id: str,
300
+ supplier_id: str,
301
+ ) -> None:
302
+ """Delete an API client supplier assignment
303
+
304
+ Args:
305
+ api_client_id: ID of the api client.
306
+ supplier_id: ID of the supplier.
307
+ """
308
+ await self._http.delete(f"/suppliers/{supplier_id}/ApiClients/Assignments/{api_client_id}")
@@ -0,0 +1,144 @@
1
+ # GENERATED by tools/codegen — DO NOT EDIT
2
+ # Source: ordercloud-openapi-v3.json
3
+ """OrderCloud ApprovalRules API resource."""
4
+
5
+ from __future__ import annotations
6
+ from typing import Any, Optional, Union
7
+
8
+ from ..models.approval import ApprovalRule
9
+ from ..models.shared import ListPage
10
+ from .base import BaseResource
11
+
12
+ __all__ = ["ApprovalRulesResource"]
13
+
14
+
15
+ class ApprovalRulesResource(BaseResource):
16
+ """Operations on OrderCloud ApprovalRules."""
17
+
18
+ async def list(
19
+ self,
20
+ buyer_id: str,
21
+ *,
22
+ search: Optional[str] = None,
23
+ search_on: Optional[str] = None,
24
+ sort_by: Optional[str] = None,
25
+ page: Optional[int] = None,
26
+ page_size: Optional[int] = None,
27
+ filters: Optional[dict[str, Any]] = None,
28
+ ) -> ListPage[ApprovalRule]:
29
+ """List approval rules
30
+
31
+ Args:
32
+ buyer_id: ID of the buyer.
33
+ search: Word or phrase to search for.
34
+ search_on: Comma-delimited list of fields to search on.
35
+ sort_by: Comma-delimited list of fields to sort by.
36
+ page: Page of results to return. When paginating through many items (> page 30), we recommend the "Last ID" method, as outlined in the Advanced Querying documentation.
37
+ page_size: Number of results to return per page.
38
+ filters: An object or dictionary representing key/value pairs to apply as filters. Valid keys are top-level properties of the returned model or 'xp.???'
39
+
40
+ Returns:
41
+ A paginated list of ApprovalRule objects.
42
+ """
43
+ params = self._build_list_params(
44
+ search=search,
45
+ search_on=search_on,
46
+ sort_by=sort_by,
47
+ page=page,
48
+ page_size=page_size,
49
+ filters=filters,
50
+ )
51
+ resp = await self._http.get(f"/buyers/{buyer_id}/approvalrules", **params)
52
+ return self._parse_list(resp.json(), ApprovalRule)
53
+
54
+ async def create(
55
+ self,
56
+ buyer_id: str,
57
+ approval_rule: Union[ApprovalRule, dict[str, Any]],
58
+ ) -> ApprovalRule:
59
+ """Create an approval rule
60
+
61
+ Args:
62
+ buyer_id: ID of the buyer.
63
+ approval_rule: A ``ApprovalRule`` model or dict. Required fields: ApprovingGroupID, RuleExpression.
64
+
65
+ Returns:
66
+ The ApprovalRule object.
67
+ """
68
+ resp = await self._http.post(
69
+ f"/buyers/{buyer_id}/approvalrules", json=self._serialize(approval_rule)
70
+ )
71
+ return ApprovalRule(**resp.json())
72
+
73
+ async def get(
74
+ self,
75
+ buyer_id: str,
76
+ approval_rule_id: str,
77
+ ) -> ApprovalRule:
78
+ """Retrieve an approval rule
79
+
80
+ Args:
81
+ buyer_id: ID of the buyer.
82
+ approval_rule_id: ID of the approval rule.
83
+
84
+ Returns:
85
+ The ApprovalRule object.
86
+ """
87
+ resp = await self._http.get(f"/buyers/{buyer_id}/approvalrules/{approval_rule_id}")
88
+ return ApprovalRule(**resp.json())
89
+
90
+ async def save(
91
+ self,
92
+ buyer_id: str,
93
+ approval_rule_id: str,
94
+ approval_rule: Union[ApprovalRule, dict[str, Any]],
95
+ ) -> ApprovalRule:
96
+ """Create or update an approval rule
97
+
98
+ Args:
99
+ buyer_id: ID of the buyer.
100
+ approval_rule_id: ID of the approval rule.
101
+ approval_rule: A ``ApprovalRule`` model or dict. Required fields: ApprovingGroupID, RuleExpression.
102
+
103
+ Returns:
104
+ The ApprovalRule object.
105
+ """
106
+ resp = await self._http.put(
107
+ f"/buyers/{buyer_id}/approvalrules/{approval_rule_id}",
108
+ json=self._serialize(approval_rule),
109
+ )
110
+ return ApprovalRule(**resp.json())
111
+
112
+ async def delete(
113
+ self,
114
+ buyer_id: str,
115
+ approval_rule_id: str,
116
+ ) -> None:
117
+ """Delete an approval rule
118
+
119
+ Args:
120
+ buyer_id: ID of the buyer.
121
+ approval_rule_id: ID of the approval rule.
122
+ """
123
+ await self._http.delete(f"/buyers/{buyer_id}/approvalrules/{approval_rule_id}")
124
+
125
+ async def patch(
126
+ self,
127
+ buyer_id: str,
128
+ approval_rule_id: str,
129
+ partial: dict[str, Any],
130
+ ) -> ApprovalRule:
131
+ """Partially update an approval rule
132
+
133
+ Args:
134
+ buyer_id: ID of the buyer.
135
+ approval_rule_id: ID of the approval rule.
136
+ partial: A dict of fields to update.
137
+
138
+ Returns:
139
+ The ApprovalRule object.
140
+ """
141
+ resp = await self._http.patch(
142
+ f"/buyers/{buyer_id}/approvalrules/{approval_rule_id}", json=partial
143
+ )
144
+ return ApprovalRule(**resp.json())