convexity-sdk 0.15.0.dev286__tar.gz → 0.15.0.dev289__tar.gz

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 (96) hide show
  1. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/PKG-INFO +1 -1
  2. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/client.py +10 -0
  3. convexity_sdk-0.15.0.dev289/convexity_sdk/resources/address_book.py +72 -0
  4. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/attributes.py +57 -0
  5. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/cost_lists.py +19 -0
  6. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/crm.py +19 -0
  7. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/erp_config.py +43 -0
  8. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/inventory.py +51 -0
  9. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/pricing.py +19 -0
  10. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/purchasing.py +19 -0
  11. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/sales.py +19 -0
  12. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/templates.py +38 -0
  13. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/.gitignore +0 -0
  14. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/README.md +0 -0
  15. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/__init__.py +0 -0
  16. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/config.py +0 -0
  17. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/exceptions.py +0 -0
  18. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/http.py +0 -0
  19. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/models/__init__.py +0 -0
  20. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/__init__.py +0 -0
  21. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/api_keys.py +0 -0
  22. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/categories.py +0 -0
  23. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/classification.py +0 -0
  24. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/connections.py +0 -0
  25. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/dashboards.py +0 -0
  26. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/datalake.py +0 -0
  27. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/datasets.py +0 -0
  28. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/email.py +0 -0
  29. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/environments.py +0 -0
  30. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/issues.py +0 -0
  31. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/organizations.py +0 -0
  32. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/projects.py +0 -0
  33. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/rbac.py +0 -0
  34. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/replenishment.py +0 -0
  35. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/runs.py +0 -0
  36. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/sales_channels.py +0 -0
  37. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/tasks.py +0 -0
  38. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/usage.py +0 -0
  39. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/warehouses.py +0 -0
  40. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/worker_tasks.py +0 -0
  41. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/convexity_sdk/resources/workspace.py +0 -0
  42. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/pyproject.toml +0 -0
  43. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/.env.example +0 -0
  44. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/README.md +0 -0
  45. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/cancel_refresh_task.py +0 -0
  46. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/compare_api_key_scopes.py +0 -0
  47. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_csv_datasets.py +0 -0
  48. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_dashboards.py +0 -0
  49. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_databricks_connections.py +0 -0
  50. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_datasets.py +0 -0
  51. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_forecast_task.py +0 -0
  52. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_org_and_project.py +0 -0
  53. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/create_single_project_api_key.py +0 -0
  54. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/crm/001_check_crm_enabled.py +0 -0
  55. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/crm/002_enable_crm.py +0 -0
  56. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/crm/003_manage_customers.py +0 -0
  57. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/crm/004_disable_crm.py +0 -0
  58. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/getting_started.py +0 -0
  59. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/001_check_inventory_enabled.py +0 -0
  60. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/002_enable_inventory.py +0 -0
  61. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/003_manage_inventory_items.py +0 -0
  62. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/004_manage_inventory_stock.py +0 -0
  63. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/005_disable_inventory.py +0 -0
  64. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/006_manage_categories.py +0 -0
  65. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/007_manage_inventory_config.py +0 -0
  66. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/inventory/008_manage_cost_lists.py +0 -0
  67. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/list_orgs_and_projects.py +0 -0
  68. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/manage_environments.py +0 -0
  69. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/manage_issues.py +0 -0
  70. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/project_usage.py +0 -0
  71. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/purchasing/001_check_purchasing_enabled.py +0 -0
  72. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/purchasing/002_enable_purchasing.py +0 -0
  73. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/purchasing/003_manage_vendors.py +0 -0
  74. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/purchasing/004_manage_purchase_orders.py +0 -0
  75. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/purchasing/005_disable_purchasing.py +0 -0
  76. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/query_datalake.py +0 -0
  77. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/quickbook/001_check_quickbook_connection.py +0 -0
  78. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/quickbook/002_create_quickbook_datasets.py +0 -0
  79. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/rbac/001_manage_roles.py +0 -0
  80. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/rbac/002_manage_assignments.py +0 -0
  81. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/rbac/003_verify_rbac_access.py +0 -0
  82. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/001_check_sales_enabled.py +0 -0
  83. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/002_enable_sales.py +0 -0
  84. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/003_manage_sales_invoices.py +0 -0
  85. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/004_manage_sales_invoice_lifecycle.py +0 -0
  86. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/005_manage_sales_orders.py +0 -0
  87. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/sales/006_disable_sales.py +0 -0
  88. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/share_dashboard.py +0 -0
  89. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/shopify/001_check_shopify_connection.py +0 -0
  90. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/shopify/002_create_shopify_datasets.py +0 -0
  91. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/uci/001_setup.py +0 -0
  92. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/uci/002_seed_inventory_from_uci.py +0 -0
  93. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/uci/003_seed_sales_from_uci.py +0 -0
  94. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/uci/004_seed_purchasing_from_uci.py +0 -0
  95. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/uci/005_run_pipelines.py +0 -0
  96. {convexity_sdk-0.15.0.dev286 → convexity_sdk-0.15.0.dev289}/samples/workspace_files.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convexity-sdk
3
- Version: 0.15.0.dev286
3
+ Version: 0.15.0.dev289
4
4
  Summary: Convexity Python SDK - programmatic access to the Convexity platform
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: convexity-api-client
@@ -12,6 +12,7 @@ from .config import SDKConfig, resolve_config
12
12
  from .http import AsyncTransport, SyncTransport
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from .resources.address_book import AddressBook
15
16
  from .resources.api_keys import ApiKeys
16
17
  from .resources.attributes import Attributes
17
18
  from .resources.categories import Categories
@@ -317,6 +318,15 @@ class ConvexityClient:
317
318
  self._erp_config = ERPConfig(self._api_client)
318
319
  return self._erp_config
319
320
 
321
+ @property
322
+ def address_book(self) -> AddressBook:
323
+ """Access ERP address book operations."""
324
+ if not hasattr(self, "_address_book"):
325
+ from .resources.address_book import AddressBook
326
+
327
+ self._address_book = AddressBook(self._api_client)
328
+ return self._address_book
329
+
320
330
  @property
321
331
  def crm(self) -> CRM:
322
332
  """Access CRM customer/account operations."""
@@ -0,0 +1,72 @@
1
+ """Address book resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, TypeVar
6
+
7
+ from convexity_api_client import AuthenticatedClient, Client
8
+ from convexity_api_client.api.v1 import erp_bulk_upsert_address_book_entries as _bulk_upsert_entries
9
+ from convexity_api_client.api.v1 import erp_list_address_book_entries as _list_entries
10
+ from convexity_api_client.models.bulk_upsert_address_book_entries_request import BulkUpsertAddressBookEntriesRequest
11
+ from convexity_api_client.models.bulk_upsert_address_book_entries_response import BulkUpsertAddressBookEntriesResponse
12
+ from convexity_api_client.models.bulk_upsert_address_book_entry_payload import BulkUpsertAddressBookEntryPayload
13
+ from convexity_api_client.models.list_address_book_entries_response import ListAddressBookEntriesResponse
14
+ from convexity_api_client.types import UNSET, Unset
15
+
16
+ ResponseT = TypeVar("ResponseT")
17
+
18
+
19
+ def _expect_response(result: object, response_type: type[ResponseT], action: str) -> ResponseT:
20
+ if not isinstance(result, response_type):
21
+ raise ValueError(f"Unexpected response when {action}: {result}")
22
+ return result
23
+
24
+
25
+ def _optional(value: Any | None) -> Any | Unset:
26
+ return UNSET if value is None else value
27
+
28
+
29
+ def _bulk_entry_payload(payload: BulkUpsertAddressBookEntryPayload | dict[str, Any]) -> BulkUpsertAddressBookEntryPayload:
30
+ return payload if isinstance(payload, BulkUpsertAddressBookEntryPayload) else BulkUpsertAddressBookEntryPayload.from_dict(payload)
31
+
32
+
33
+ class AddressBook:
34
+ """Synchronous sub-client for ERP address book entries."""
35
+
36
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
37
+ self._client = api_client
38
+
39
+ def list_entries(
40
+ self,
41
+ *,
42
+ project_id: str,
43
+ owner_type: str,
44
+ owner_id: str,
45
+ is_active: bool | None = None,
46
+ limit: int = 50,
47
+ offset: int = 0,
48
+ ) -> ListAddressBookEntriesResponse:
49
+ """List address book entries for an owner."""
50
+ result = _list_entries.sync(
51
+ client=self._client,
52
+ owner_type=owner_type,
53
+ owner_id=owner_id,
54
+ is_active=_optional(is_active),
55
+ limit=limit,
56
+ offset=offset,
57
+ project_id=project_id,
58
+ )
59
+ if isinstance(result, ListAddressBookEntriesResponse):
60
+ return result
61
+ return ListAddressBookEntriesResponse(entries=[], total=0)
62
+
63
+ def bulk_upsert_entries(
64
+ self,
65
+ *,
66
+ project_id: str,
67
+ entries: list[BulkUpsertAddressBookEntryPayload | dict[str, Any]],
68
+ ) -> BulkUpsertAddressBookEntriesResponse:
69
+ """Bulk upsert address book entries by owner and label."""
70
+ body = BulkUpsertAddressBookEntriesRequest(entries=[_bulk_entry_payload(entry) for entry in entries])
71
+ result = _bulk_upsert_entries.sync(client=self._client, body=body, project_id=project_id)
72
+ return _expect_response(result, BulkUpsertAddressBookEntriesResponse, "bulk upserting address book entries")
@@ -10,6 +10,9 @@ from typing import Any, TypeVar, cast
10
10
 
11
11
  from convexity_api_client import AuthenticatedClient, Client
12
12
  from convexity_api_client.api.v1 import inventory_add_attribute_line as _add_attribute_line
13
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_attribute_values as _bulk_upsert_attribute_values
14
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_attributes as _bulk_upsert_attributes
15
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_template_attribute_lines as _bulk_upsert_template_attribute_lines
13
16
  from convexity_api_client.api.v1 import inventory_create_attribute as _create_attribute
14
17
  from convexity_api_client.api.v1 import inventory_create_attribute_value as _create_attribute_value
15
18
  from convexity_api_client.api.v1 import inventory_get_attribute as _get_attribute
@@ -19,6 +22,15 @@ from convexity_api_client.api.v1 import inventory_list_attributes as _list_attri
19
22
  from convexity_api_client.api.v1 import inventory_remove_attribute_line as _remove_attribute_line
20
23
  from convexity_api_client.models.add_attribute_line_request import AddAttributeLineRequest
21
24
  from convexity_api_client.models.attribute_with_values_response import AttributeWithValuesResponse
25
+ from convexity_api_client.models.bulk_upsert_item_attribute_payload import BulkUpsertItemAttributePayload
26
+ from convexity_api_client.models.bulk_upsert_item_attribute_value_payload import BulkUpsertItemAttributeValuePayload
27
+ from convexity_api_client.models.bulk_upsert_item_attribute_values_request import BulkUpsertItemAttributeValuesRequest
28
+ from convexity_api_client.models.bulk_upsert_item_attribute_values_response import BulkUpsertItemAttributeValuesResponse
29
+ from convexity_api_client.models.bulk_upsert_item_attributes_request import BulkUpsertItemAttributesRequest
30
+ from convexity_api_client.models.bulk_upsert_item_attributes_response import BulkUpsertItemAttributesResponse
31
+ from convexity_api_client.models.bulk_upsert_template_attribute_line_payload import BulkUpsertTemplateAttributeLinePayload
32
+ from convexity_api_client.models.bulk_upsert_template_attribute_lines_request import BulkUpsertTemplateAttributeLinesRequest
33
+ from convexity_api_client.models.bulk_upsert_template_attribute_lines_response import BulkUpsertTemplateAttributeLinesResponse
22
34
  from convexity_api_client.models.create_item_attribute_request import CreateItemAttributeRequest
23
35
  from convexity_api_client.models.create_item_attribute_value_request import CreateItemAttributeValueRequest
24
36
  from convexity_api_client.models.item_attribute_response import ItemAttributeResponse
@@ -44,6 +56,18 @@ def _optional(value: Any | None) -> Any | Unset:
44
56
  return UNSET if value is None else value
45
57
 
46
58
 
59
+ def _bulk_attribute_payload(payload: BulkUpsertItemAttributePayload | dict[str, Any]) -> BulkUpsertItemAttributePayload:
60
+ return payload if isinstance(payload, BulkUpsertItemAttributePayload) else BulkUpsertItemAttributePayload.from_dict(payload)
61
+
62
+
63
+ def _bulk_attribute_value_payload(payload: BulkUpsertItemAttributeValuePayload | dict[str, Any]) -> BulkUpsertItemAttributeValuePayload:
64
+ return payload if isinstance(payload, BulkUpsertItemAttributeValuePayload) else BulkUpsertItemAttributeValuePayload.from_dict(payload)
65
+
66
+
67
+ def _bulk_attribute_line_payload(payload: BulkUpsertTemplateAttributeLinePayload | dict[str, Any]) -> BulkUpsertTemplateAttributeLinePayload:
68
+ return payload if isinstance(payload, BulkUpsertTemplateAttributeLinePayload) else BulkUpsertTemplateAttributeLinePayload.from_dict(payload)
69
+
70
+
47
71
  class Attributes:
48
72
  """Synchronous sub-client for item attribute management."""
49
73
 
@@ -111,6 +135,17 @@ class Attributes:
111
135
  return result
112
136
  return ListItemAttributesResponse(attributes=[], total=0)
113
137
 
138
+ def bulk_upsert_attributes(
139
+ self,
140
+ *,
141
+ project_id: str,
142
+ attributes: list[BulkUpsertItemAttributePayload | dict[str, Any]],
143
+ ) -> BulkUpsertItemAttributesResponse:
144
+ """Bulk upsert item attributes by code."""
145
+ body = BulkUpsertItemAttributesRequest(attributes=[_bulk_attribute_payload(attribute) for attribute in attributes])
146
+ result = _bulk_upsert_attributes.sync(client=self._client, body=body, project_id=project_id)
147
+ return _expect_response(result, BulkUpsertItemAttributesResponse, "bulk upserting item attributes")
148
+
114
149
  # -- Attribute Values -----------------------------------------------------
115
150
 
116
151
  def create_attribute_value(
@@ -153,6 +188,17 @@ class Attributes:
153
188
  return result
154
189
  return ListItemAttributeValuesResponse(values=[], total=0)
155
190
 
191
+ def bulk_upsert_attribute_values(
192
+ self,
193
+ *,
194
+ project_id: str,
195
+ values: list[BulkUpsertItemAttributeValuePayload | dict[str, Any]],
196
+ ) -> BulkUpsertItemAttributeValuesResponse:
197
+ """Bulk upsert item attribute values by attribute and value code."""
198
+ body = BulkUpsertItemAttributeValuesRequest(values=[_bulk_attribute_value_payload(value) for value in values])
199
+ result = _bulk_upsert_attribute_values.sync(client=self._client, body=body, project_id=project_id)
200
+ return _expect_response(result, BulkUpsertItemAttributeValuesResponse, "bulk upserting item attribute values")
201
+
156
202
  # -- Template Attribute Lines ---------------------------------------------
157
203
 
158
204
  def add_attribute_line(
@@ -197,3 +243,14 @@ class Attributes:
197
243
  if isinstance(result, ListTemplateAttributeLineDetailsResponse):
198
244
  return result
199
245
  return ListTemplateAttributeLineDetailsResponse(lines=[])
246
+
247
+ def bulk_upsert_template_attribute_lines(
248
+ self,
249
+ *,
250
+ project_id: str,
251
+ lines: list[BulkUpsertTemplateAttributeLinePayload | dict[str, Any]],
252
+ ) -> BulkUpsertTemplateAttributeLinesResponse:
253
+ """Bulk upsert template attribute lines and enabled values."""
254
+ body = BulkUpsertTemplateAttributeLinesRequest(lines=[_bulk_attribute_line_payload(line) for line in lines])
255
+ result = _bulk_upsert_template_attribute_lines.sync(client=self._client, body=body, project_id=project_id)
256
+ return _expect_response(result, BulkUpsertTemplateAttributeLinesResponse, "bulk upserting template attribute lines")
@@ -11,6 +11,7 @@ from datetime import datetime
11
11
  from typing import Any, TypeVar, cast
12
12
 
13
13
  from convexity_api_client import AuthenticatedClient, Client
14
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_cost_rules as _bulk_upsert_cost_rules
14
15
  from convexity_api_client.api.v1 import inventory_create_cost_list as _create_cost_list
15
16
  from convexity_api_client.api.v1 import inventory_create_cost_rule as _create_cost_rule
16
17
  from convexity_api_client.api.v1 import inventory_delete_cost_list as _delete_cost_list
@@ -21,6 +22,9 @@ from convexity_api_client.api.v1 import inventory_list_cost_lists as _list_cost_
21
22
  from convexity_api_client.api.v1 import inventory_list_cost_rules as _list_cost_rules
22
23
  from convexity_api_client.api.v1 import inventory_update_cost_list as _update_cost_list
23
24
  from convexity_api_client.api.v1 import inventory_update_cost_rule as _update_cost_rule
25
+ from convexity_api_client.models.bulk_upsert_cost_rule_payload import BulkUpsertCostRulePayload
26
+ from convexity_api_client.models.bulk_upsert_cost_rules_request import BulkUpsertCostRulesRequest
27
+ from convexity_api_client.models.bulk_upsert_cost_rules_response import BulkUpsertCostRulesResponse
24
28
  from convexity_api_client.models.cost_list_response import CostListResponse
25
29
  from convexity_api_client.models.cost_rule_response import CostRuleResponse
26
30
  from convexity_api_client.models.create_cost_list_request import CreateCostListRequest
@@ -45,6 +49,10 @@ def _optional(value: Any | None) -> Any | Unset:
45
49
  return UNSET if value is None else value
46
50
 
47
51
 
52
+ def _bulk_cost_rule_payload(payload: BulkUpsertCostRulePayload | dict[str, Any]) -> BulkUpsertCostRulePayload:
53
+ return payload if isinstance(payload, BulkUpsertCostRulePayload) else BulkUpsertCostRulePayload.from_dict(payload)
54
+
55
+
48
56
  def _to_item_match(value: dict[str, Any] | None) -> ItemMatchInput | Unset:
49
57
  if value is None:
50
58
  return UNSET
@@ -237,3 +245,14 @@ class CostLists:
237
245
  def delete_cost_rule(self, cost_rule_id: str, *, project_id: str) -> CostRuleResponse:
238
246
  result = _delete_cost_rule.sync(cost_rule_id, client=self._client, project_id=project_id)
239
247
  return _expect_response(result, CostRuleResponse, "deleting cost rule")
248
+
249
+ def bulk_upsert_cost_rules(
250
+ self,
251
+ *,
252
+ project_id: str,
253
+ rules: list[BulkUpsertCostRulePayload | dict[str, Any]],
254
+ ) -> BulkUpsertCostRulesResponse:
255
+ """Bulk upsert cost rules by import key."""
256
+ body = BulkUpsertCostRulesRequest(rules=[_bulk_cost_rule_payload(rule) for rule in rules])
257
+ result = _bulk_upsert_cost_rules.sync(client=self._client, body=body, project_id=project_id)
258
+ return _expect_response(result, BulkUpsertCostRulesResponse, "bulk upserting cost rules")
@@ -5,11 +5,15 @@ from __future__ import annotations
5
5
  from typing import Any, TypeVar, cast
6
6
 
7
7
  from convexity_api_client import AuthenticatedClient, Client
8
+ from convexity_api_client.api.v1 import crm_bulk_upsert_customers as _bulk_upsert_customers
8
9
  from convexity_api_client.api.v1 import crm_create_customer as _create_customer
9
10
  from convexity_api_client.api.v1 import crm_delete_customer as _delete_customer
10
11
  from convexity_api_client.api.v1 import crm_get_customer as _get_customer
11
12
  from convexity_api_client.api.v1 import crm_list_customers as _list_customers
12
13
  from convexity_api_client.api.v1 import crm_update_customer as _update_customer
14
+ from convexity_api_client.models.bulk_upsert_customer_payload import BulkUpsertCustomerPayload
15
+ from convexity_api_client.models.bulk_upsert_customers_request import BulkUpsertCustomersRequest
16
+ from convexity_api_client.models.bulk_upsert_customers_response import BulkUpsertCustomersResponse
13
17
  from convexity_api_client.models.create_customer_request import CreateCustomerRequest
14
18
  from convexity_api_client.models.customer_response import CustomerResponse
15
19
  from convexity_api_client.models.list_customers_response import ListCustomersResponse
@@ -29,6 +33,10 @@ def _optional(value: Any | None) -> Any | Unset:
29
33
  return UNSET if value is None else value
30
34
 
31
35
 
36
+ def _bulk_customer_payload(payload: BulkUpsertCustomerPayload | dict[str, Any]) -> BulkUpsertCustomerPayload:
37
+ return payload if isinstance(payload, BulkUpsertCustomerPayload) else BulkUpsertCustomerPayload.from_dict(payload)
38
+
39
+
32
40
  class CRM:
33
41
  """Synchronous sub-client for CRM customer operations."""
34
42
 
@@ -66,6 +74,17 @@ class CRM:
66
74
  result = _create_customer.sync(client=self._client, body=body, project_id=project_id)
67
75
  return _expect_response(result, CustomerResponse, "creating customer")
68
76
 
77
+ def bulk_upsert_customers(
78
+ self,
79
+ *,
80
+ project_id: str,
81
+ customers: list[BulkUpsertCustomerPayload | dict[str, Any]],
82
+ ) -> BulkUpsertCustomersResponse:
83
+ """Bulk upsert CRM customers by code."""
84
+ body = BulkUpsertCustomersRequest(customers=[_bulk_customer_payload(customer) for customer in customers])
85
+ result = _bulk_upsert_customers.sync(client=self._client, body=body, project_id=project_id)
86
+ return _expect_response(result, BulkUpsertCustomersResponse, "bulk upserting customers")
87
+
69
88
  def list_customers(
70
89
  self,
71
90
  *,
@@ -5,13 +5,19 @@ from __future__ import annotations
5
5
  from typing import Any, TypeVar, cast
6
6
 
7
7
  from convexity_api_client import AuthenticatedClient, Client
8
+ from convexity_api_client.api.v1 import erp_config_bulk_upsert_status_mappings as _bulk_upsert_status_mappings
8
9
  from convexity_api_client.api.v1 import erp_config_get_module_gate as _get_module_gate
9
10
  from convexity_api_client.api.v1 import erp_config_list_module_gates as _list_module_gates
11
+ from convexity_api_client.api.v1 import erp_config_list_status_mappings as _list_status_mappings
10
12
  from convexity_api_client.api.v1 import erp_config_upsert_module_gate as _upsert_module_gate
13
+ from convexity_api_client.models.bulk_upsert_status_mappings_request import BulkUpsertStatusMappingsRequest
14
+ from convexity_api_client.models.bulk_upsert_status_mappings_response import BulkUpsertStatusMappingsResponse
11
15
  from convexity_api_client.models.erp_module_gate_response import ERPModuleGateResponse
12
16
  from convexity_api_client.models.erp_module_key import ERPModuleKey
13
17
  from convexity_api_client.models.list_module_gates_response import ListModuleGatesResponse
18
+ from convexity_api_client.models.list_status_mappings_response import ListStatusMappingsResponse
14
19
  from convexity_api_client.models.upsert_erp_module_gate_request import UpsertERPModuleGateRequest
20
+ from convexity_api_client.models.upsert_status_mapping_request import UpsertStatusMappingRequest
15
21
  from convexity_api_client.types import UNSET, Unset
16
22
 
17
23
  ResponseT = TypeVar("ResponseT")
@@ -33,6 +39,10 @@ def _optional(value: Any | None) -> Any | Unset:
33
39
  return UNSET if value is None else value
34
40
 
35
41
 
42
+ def _status_mapping_payload(payload: UpsertStatusMappingRequest | dict[str, Any]) -> UpsertStatusMappingRequest:
43
+ return payload if isinstance(payload, UpsertStatusMappingRequest) else UpsertStatusMappingRequest.from_dict(payload)
44
+
45
+
36
46
  class ERPConfig:
37
47
  """Synchronous sub-client for ERP configuration and module gates."""
38
48
 
@@ -106,3 +116,36 @@ class ERPConfig:
106
116
  normalized_key = _module_key(module_key)
107
117
  gates = self.list_module_gates(project_id=project_id, limit=100)
108
118
  return any(gate.module_key == normalized_key and gate.is_enabled for gate in gates.gates)
119
+
120
+ def list_status_mappings(
121
+ self,
122
+ *,
123
+ project_id: str,
124
+ source_system: str | None = None,
125
+ entity_type: str | None = None,
126
+ limit: int = 50,
127
+ offset: int = 0,
128
+ ) -> ListStatusMappingsResponse:
129
+ """List ERP status mappings for a project."""
130
+ result = _list_status_mappings.sync(
131
+ client=self._client,
132
+ source_system=_optional(source_system),
133
+ entity_type=_optional(entity_type),
134
+ limit=limit,
135
+ offset=offset,
136
+ project_id=project_id,
137
+ )
138
+ if isinstance(result, ListStatusMappingsResponse):
139
+ return result
140
+ return ListStatusMappingsResponse(mappings=[], total=0)
141
+
142
+ def bulk_upsert_status_mappings(
143
+ self,
144
+ *,
145
+ project_id: str,
146
+ mappings: list[UpsertStatusMappingRequest | dict[str, Any]],
147
+ ) -> BulkUpsertStatusMappingsResponse:
148
+ """Bulk upsert ERP status mappings."""
149
+ body = BulkUpsertStatusMappingsRequest(mappings=[_status_mapping_payload(mapping) for mapping in mappings])
150
+ result = _bulk_upsert_status_mappings.sync(client=self._client, body=body, project_id=project_id)
151
+ return _expect_response(result, BulkUpsertStatusMappingsResponse, "bulk upserting ERP status mappings")
@@ -15,6 +15,7 @@ from convexity_api_client.api.v1 import inventory_bulk_import_items as _bulk_imp
15
15
  from convexity_api_client.api.v1 import (
16
16
  inventory_bulk_post_stock_transactions as _bulk_post_stock_transactions,
17
17
  )
18
+ from convexity_api_client.api.v1 import inventory_bulk_reconcile_stock_balances as _bulk_reconcile_stock_balances
18
19
  from convexity_api_client.api.v1 import inventory_deactivate_item as _deactivate_item
19
20
  from convexity_api_client.api.v1 import inventory_get_item as _get_item
20
21
  from convexity_api_client.api.v1 import (
@@ -38,6 +39,9 @@ from convexity_api_client.models.bulk_import_inventory_item_request import BulkI
38
39
  from convexity_api_client.models.bulk_import_inventory_item_response import BulkImportInventoryItemResponse
39
40
  from convexity_api_client.models.bulk_post_stock_transactions_request import BulkPostStockTransactionsRequest
40
41
  from convexity_api_client.models.bulk_post_stock_transactions_response import BulkPostStockTransactionsResponse
42
+ from convexity_api_client.models.bulk_reconcile_stock_balance_payload import BulkReconcileStockBalancePayload
43
+ from convexity_api_client.models.bulk_reconcile_stock_balances_request import BulkReconcileStockBalancesRequest
44
+ from convexity_api_client.models.bulk_reconcile_stock_balances_response import BulkReconcileStockBalancesResponse
41
45
  from convexity_api_client.models.create_inventory_item_request import CreateInventoryItemRequest
42
46
  from convexity_api_client.models.inventory_item_response import InventoryItemResponse
43
47
  from convexity_api_client.models.list_inventory_items_response import ListInventoryItemsResponse
@@ -70,6 +74,18 @@ def _optional(value: Any | None) -> Any | Unset:
70
74
  return UNSET if value is None else value
71
75
 
72
76
 
77
+ def _bulk_reconcile_payload(payload: BulkReconcileStockBalancePayload | dict[str, Any]) -> BulkReconcileStockBalancePayload:
78
+ return payload if isinstance(payload, BulkReconcileStockBalancePayload) else BulkReconcileStockBalancePayload.from_dict(payload)
79
+
80
+
81
+ def _response_count(value: int | Unset) -> int:
82
+ return value if isinstance(value, int) else 0
83
+
84
+
85
+ def _response_errors(value: list[str] | Unset) -> list[str]:
86
+ return [] if isinstance(value, Unset) else value
87
+
88
+
73
89
  class Inventory:
74
90
  """Synchronous sub-client for inventory item and stock operations."""
75
91
 
@@ -238,6 +254,41 @@ class Inventory:
238
254
  errors=all_errors if all_errors else UNSET,
239
255
  )
240
256
 
257
+ def bulk_reconcile_stock_balances(
258
+ self,
259
+ *,
260
+ project_id: str,
261
+ balances: Sequence[BulkReconcileStockBalancePayload | dict[str, Any]],
262
+ chunk_size: int = 1000,
263
+ ) -> BulkReconcileStockBalancesResponse:
264
+ """Bulk reconcile stock balances to exact target on-hand quantities."""
265
+ all_balances = [_bulk_reconcile_payload(balance) for balance in balances]
266
+ if len(all_balances) <= chunk_size:
267
+ body = BulkReconcileStockBalancesRequest(balances=all_balances)
268
+ result = _bulk_reconcile_stock_balances.sync(client=self._client, body=body, project_id=project_id)
269
+ return _expect_response(result, BulkReconcileStockBalancesResponse, "bulk reconciling stock balances")
270
+
271
+ total_created = 0
272
+ total_updated = 0
273
+ total_skipped = 0
274
+ all_errors: list[str] = []
275
+ for i in range(0, len(all_balances), chunk_size):
276
+ chunk = all_balances[i : i + chunk_size]
277
+ body = BulkReconcileStockBalancesRequest(balances=chunk)
278
+ result = _bulk_reconcile_stock_balances.sync(client=self._client, body=body, project_id=project_id)
279
+ response = _expect_response(result, BulkReconcileStockBalancesResponse, "bulk reconciling stock balances")
280
+ total_created += _response_count(response.created)
281
+ total_updated += _response_count(response.updated)
282
+ total_skipped += _response_count(response.skipped)
283
+ all_errors.extend(_response_errors(response.errors))
284
+
285
+ return BulkReconcileStockBalancesResponse(
286
+ created=total_created,
287
+ updated=total_updated,
288
+ skipped=total_skipped,
289
+ errors=all_errors,
290
+ )
291
+
241
292
  def adjust_stock(
242
293
  self,
243
294
  *,
@@ -11,6 +11,7 @@ from datetime import datetime
11
11
  from typing import Any, TypeVar, cast
12
12
 
13
13
  from convexity_api_client import AuthenticatedClient, Client
14
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_price_rules as _bulk_upsert_price_rules
14
15
  from convexity_api_client.api.v1 import inventory_create_price_list as _create_price_list
15
16
  from convexity_api_client.api.v1 import inventory_create_price_rule as _create_price_rule
16
17
  from convexity_api_client.api.v1 import inventory_delete_price_list as _delete_price_list
@@ -22,6 +23,9 @@ from convexity_api_client.api.v1 import inventory_list_price_rules as _list_pric
22
23
  from convexity_api_client.api.v1 import inventory_resolve_price as _resolve_price
23
24
  from convexity_api_client.api.v1 import inventory_update_price_list as _update_price_list
24
25
  from convexity_api_client.api.v1 import inventory_update_price_rule as _update_price_rule
26
+ from convexity_api_client.models.bulk_upsert_price_rule_payload import BulkUpsertPriceRulePayload
27
+ from convexity_api_client.models.bulk_upsert_price_rules_request import BulkUpsertPriceRulesRequest
28
+ from convexity_api_client.models.bulk_upsert_price_rules_response import BulkUpsertPriceRulesResponse
25
29
  from convexity_api_client.models.create_price_list_request import CreatePriceListRequest
26
30
  from convexity_api_client.models.create_price_rule_request import CreatePriceRuleRequest
27
31
  from convexity_api_client.models.item_match_input import ItemMatchInput
@@ -55,6 +59,10 @@ def _optional(value: Any | None) -> Any | Unset:
55
59
  return UNSET if value is None else value
56
60
 
57
61
 
62
+ def _bulk_price_rule_payload(payload: BulkUpsertPriceRulePayload | dict[str, Any]) -> BulkUpsertPriceRulePayload:
63
+ return payload if isinstance(payload, BulkUpsertPriceRulePayload) else BulkUpsertPriceRulePayload.from_dict(payload)
64
+
65
+
58
66
  def _to_item_match(value: dict[str, Any] | None) -> ItemMatchInput | Unset:
59
67
  if value is None:
60
68
  return UNSET
@@ -258,6 +266,17 @@ class Pricing:
258
266
  result = _delete_price_rule.sync(price_rule_id, client=self._client, project_id=project_id)
259
267
  return _expect_response(result, PriceRuleResponse, "deleting price rule")
260
268
 
269
+ def bulk_upsert_price_rules(
270
+ self,
271
+ *,
272
+ project_id: str,
273
+ rules: list[BulkUpsertPriceRulePayload | dict[str, Any]],
274
+ ) -> BulkUpsertPriceRulesResponse:
275
+ """Bulk upsert price rules by import key."""
276
+ body = BulkUpsertPriceRulesRequest(rules=[_bulk_price_rule_payload(rule) for rule in rules])
277
+ result = _bulk_upsert_price_rules.sync(client=self._client, body=body, project_id=project_id)
278
+ return _expect_response(result, BulkUpsertPriceRulesResponse, "bulk upserting price rules")
279
+
261
280
  # -- Price resolution ----------------------------------------------------
262
281
 
263
282
  def resolve_price(
@@ -11,6 +11,7 @@ from convexity_api_client.api.v1 import purchasing_approve_po as _approve_po
11
11
  from convexity_api_client.api.v1 import purchasing_batch_delete_pos as _batch_delete_pos
12
12
  from convexity_api_client.api.v1 import purchasing_batch_delete_vendors as _batch_delete_vendors
13
13
  from convexity_api_client.api.v1 import purchasing_bulk_create_pos as _bulk_create_pos
14
+ from convexity_api_client.api.v1 import purchasing_bulk_upsert_vendors as _bulk_upsert_vendors
14
15
  from convexity_api_client.api.v1 import purchasing_cancel_po as _cancel_po
15
16
  from convexity_api_client.api.v1 import purchasing_confirm_po as _confirm_po
16
17
  from convexity_api_client.api.v1 import purchasing_create_po as _create_po
@@ -30,6 +31,9 @@ from convexity_api_client.models.batch_delete_vendors_request import BatchDelete
30
31
  from convexity_api_client.models.batch_delete_vendors_response import BatchDeleteVendorsResponse
31
32
  from convexity_api_client.models.bulk_create_purchase_orders_request import BulkCreatePurchaseOrdersRequest
32
33
  from convexity_api_client.models.bulk_create_purchase_orders_response import BulkCreatePurchaseOrdersResponse
34
+ from convexity_api_client.models.bulk_upsert_vendor_payload import BulkUpsertVendorPayload
35
+ from convexity_api_client.models.bulk_upsert_vendors_request import BulkUpsertVendorsRequest
36
+ from convexity_api_client.models.bulk_upsert_vendors_response import BulkUpsertVendorsResponse
33
37
  from convexity_api_client.models.cancel_purchase_order_request import CancelPurchaseOrderRequest
34
38
  from convexity_api_client.models.canonical_status import CanonicalStatus
35
39
  from convexity_api_client.models.create_purchase_order_request import CreatePurchaseOrderRequest
@@ -57,6 +61,10 @@ def _optional(value: Any | None) -> Any | Unset:
57
61
  return UNSET if value is None else value
58
62
 
59
63
 
64
+ def _bulk_vendor_payload(payload: BulkUpsertVendorPayload | dict[str, Any]) -> BulkUpsertVendorPayload:
65
+ return payload if isinstance(payload, BulkUpsertVendorPayload) else BulkUpsertVendorPayload.from_dict(payload)
66
+
67
+
60
68
  def _po_status(value: CanonicalStatus | str | None) -> CanonicalStatus | None:
61
69
  if value is None or isinstance(value, CanonicalStatus):
62
70
  return value
@@ -122,6 +130,17 @@ class Purchasing:
122
130
  result = _create_vendor.sync(client=self._client, body=body, project_id=project_id)
123
131
  return _expect_response(result, VendorResponse, "creating vendor")
124
132
 
133
+ def bulk_upsert_vendors(
134
+ self,
135
+ *,
136
+ project_id: str,
137
+ vendors: list[BulkUpsertVendorPayload | dict[str, Any]],
138
+ ) -> BulkUpsertVendorsResponse:
139
+ """Bulk upsert vendors by code."""
140
+ body = BulkUpsertVendorsRequest(vendors=[_bulk_vendor_payload(vendor) for vendor in vendors])
141
+ result = _bulk_upsert_vendors.sync(client=self._client, body=body, project_id=project_id)
142
+ return _expect_response(result, BulkUpsertVendorsResponse, "bulk upserting vendors")
143
+
125
144
  def list_vendors(
126
145
  self,
127
146
  *,
@@ -8,6 +8,7 @@ from typing import Any, TypeVar, cast
8
8
 
9
9
  from convexity_api_client import AuthenticatedClient, Client
10
10
  from convexity_api_client.api.v1 import sales_batch_delete_orders as _batch_delete_orders
11
+ from convexity_api_client.api.v1 import sales_bulk_upsert_orders as _bulk_upsert_orders
11
12
  from convexity_api_client.api.v1 import sales_cancel_invoice as _cancel_invoice
12
13
  from convexity_api_client.api.v1 import sales_create_invoice as _create_invoice
13
14
  from convexity_api_client.api.v1 import sales_create_order as _create_order
@@ -22,6 +23,9 @@ from convexity_api_client.api.v1 import sales_resolve_invoice_dispute as _resolv
22
23
  from convexity_api_client.api.v1 import sales_update_invoice as _update_invoice
23
24
  from convexity_api_client.models.batch_delete_sales_orders_request import BatchDeleteSalesOrdersRequest
24
25
  from convexity_api_client.models.batch_delete_sales_orders_response import BatchDeleteSalesOrdersResponse
26
+ from convexity_api_client.models.bulk_upsert_sales_order_payload import BulkUpsertSalesOrderPayload
27
+ from convexity_api_client.models.bulk_upsert_sales_orders_request import BulkUpsertSalesOrdersRequest
28
+ from convexity_api_client.models.bulk_upsert_sales_orders_response import BulkUpsertSalesOrdersResponse
25
29
  from convexity_api_client.models.cancel_sales_invoice_request import CancelSalesInvoiceRequest
26
30
  from convexity_api_client.models.canonical_status import CanonicalStatus
27
31
  from convexity_api_client.models.create_sales_invoice_request import CreateSalesInvoiceRequest
@@ -74,6 +78,10 @@ def _optional(value: Any | None) -> Any | Unset:
74
78
  return UNSET if value is None else value
75
79
 
76
80
 
81
+ def _bulk_sales_order_payload(payload: BulkUpsertSalesOrderPayload | dict[str, Any]) -> BulkUpsertSalesOrderPayload:
82
+ return payload if isinstance(payload, BulkUpsertSalesOrderPayload) else BulkUpsertSalesOrderPayload.from_dict(payload)
83
+
84
+
77
85
  def _invoice_source(value: SalesInvoiceSource | str) -> SalesInvoiceSource:
78
86
  if isinstance(value, SalesInvoiceSource):
79
87
  return value
@@ -319,6 +327,17 @@ class Sales:
319
327
  result = _create_order.sync(client=self._client, body=body, project_id=project_id)
320
328
  return _expect_response(result, SalesOrderResponse, "creating sales order")
321
329
 
330
+ def bulk_upsert_orders(
331
+ self,
332
+ *,
333
+ project_id: str,
334
+ orders: list[BulkUpsertSalesOrderPayload | dict[str, Any]],
335
+ ) -> BulkUpsertSalesOrdersResponse:
336
+ """Bulk upsert sales orders by sales order number."""
337
+ body = BulkUpsertSalesOrdersRequest(orders=[_bulk_sales_order_payload(order) for order in orders])
338
+ result = _bulk_upsert_orders.sync(client=self._client, body=body, project_id=project_id)
339
+ return _expect_response(result, BulkUpsertSalesOrdersResponse, "bulk upserting sales orders")
340
+
322
341
  def list_orders(
323
342
  self,
324
343
  *,
@@ -12,6 +12,8 @@ from __future__ import annotations
12
12
  from typing import Any, TypeVar, cast
13
13
 
14
14
  from convexity_api_client import AuthenticatedClient, Client
15
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_templates as _bulk_upsert_templates
16
+ from convexity_api_client.api.v1 import inventory_bulk_upsert_variants as _bulk_upsert_variants
15
17
  from convexity_api_client.api.v1 import inventory_create_template as _create_template
16
18
  from convexity_api_client.api.v1 import inventory_create_variant as _create_variant
17
19
  from convexity_api_client.api.v1 import inventory_delete_identifier as _delete_identifier
@@ -20,6 +22,12 @@ from convexity_api_client.api.v1 import inventory_list_identifiers as _list_iden
20
22
  from convexity_api_client.api.v1 import inventory_list_templates as _list_templates
21
23
  from convexity_api_client.api.v1 import inventory_update_template as _update_template
22
24
  from convexity_api_client.api.v1 import inventory_upsert_identifier as _upsert_identifier
25
+ from convexity_api_client.models.bulk_upsert_item_template_payload import BulkUpsertItemTemplatePayload
26
+ from convexity_api_client.models.bulk_upsert_item_templates_request import BulkUpsertItemTemplatesRequest
27
+ from convexity_api_client.models.bulk_upsert_item_templates_response import BulkUpsertItemTemplatesResponse
28
+ from convexity_api_client.models.bulk_upsert_item_variant_payload import BulkUpsertItemVariantPayload
29
+ from convexity_api_client.models.bulk_upsert_item_variants_request import BulkUpsertItemVariantsRequest
30
+ from convexity_api_client.models.bulk_upsert_item_variants_response import BulkUpsertItemVariantsResponse
23
31
  from convexity_api_client.models.create_item_template_request import CreateItemTemplateRequest
24
32
  from convexity_api_client.models.create_item_variant_request import CreateItemVariantRequest
25
33
  from convexity_api_client.models.create_item_variant_request_attribute_values import (
@@ -61,6 +69,14 @@ def _optional(value: Any | None) -> Any | Unset:
61
69
  return UNSET if value is None else value
62
70
 
63
71
 
72
+ def _bulk_template_payload(payload: BulkUpsertItemTemplatePayload | dict[str, Any]) -> BulkUpsertItemTemplatePayload:
73
+ return payload if isinstance(payload, BulkUpsertItemTemplatePayload) else BulkUpsertItemTemplatePayload.from_dict(payload)
74
+
75
+
76
+ def _bulk_variant_payload(payload: BulkUpsertItemVariantPayload | dict[str, Any]) -> BulkUpsertItemVariantPayload:
77
+ return payload if isinstance(payload, BulkUpsertItemVariantPayload) else BulkUpsertItemVariantPayload.from_dict(payload)
78
+
79
+
64
80
  class Templates:
65
81
  """Synchronous sub-client for item templates, variants, and identifiers."""
66
82
 
@@ -153,6 +169,17 @@ class Templates:
153
169
  result = _update_template.sync(template_id, client=self._client, body=body, project_id=project_id)
154
170
  return _expect_response(result, ItemTemplateResponse, "updating item template")
155
171
 
172
+ def bulk_upsert_templates(
173
+ self,
174
+ *,
175
+ project_id: str,
176
+ templates: list[BulkUpsertItemTemplatePayload | dict[str, Any]],
177
+ ) -> BulkUpsertItemTemplatesResponse:
178
+ """Bulk upsert item templates by code."""
179
+ body = BulkUpsertItemTemplatesRequest(templates=[_bulk_template_payload(template) for template in templates])
180
+ result = _bulk_upsert_templates.sync(client=self._client, body=body, project_id=project_id)
181
+ return _expect_response(result, BulkUpsertItemTemplatesResponse, "bulk upserting item templates")
182
+
156
183
  # -- Variants -------------------------------------------------------------
157
184
 
158
185
  def create_variant(
@@ -190,6 +217,17 @@ class Templates:
190
217
  result = _create_variant.sync(template_id, client=self._client, body=body, project_id=project_id)
191
218
  return _expect_response(result, ItemVariantResponse, "creating item variant")
192
219
 
220
+ def bulk_upsert_variants(
221
+ self,
222
+ *,
223
+ project_id: str,
224
+ variants: list[BulkUpsertItemVariantPayload | dict[str, Any]],
225
+ ) -> BulkUpsertItemVariantsResponse:
226
+ """Bulk upsert inventory variants by SKU under their templates."""
227
+ body = BulkUpsertItemVariantsRequest(variants=[_bulk_variant_payload(variant) for variant in variants])
228
+ result = _bulk_upsert_variants.sync(client=self._client, body=body, project_id=project_id)
229
+ return _expect_response(result, BulkUpsertItemVariantsResponse, "bulk upserting item variants")
230
+
193
231
  # -- Identifiers ----------------------------------------------------------
194
232
 
195
233
  def upsert_identifier(