spyreapi 0.0.2__tar.gz → 0.0.3__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 (28) hide show
  1. spyreapi-0.0.3/MANIFEST.in +4 -0
  2. {spyreapi-0.0.2/src/spyreapi.egg-info → spyreapi-0.0.3}/PKG-INFO +18 -1
  3. {spyreapi-0.0.2 → spyreapi-0.0.3}/README.md +17 -0
  4. {spyreapi-0.0.2 → spyreapi-0.0.3}/pyproject.toml +1 -1
  5. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Models/sales_models.py +1 -1
  6. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Models/shared_models.py +30 -1
  7. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/client.py +6 -1
  8. spyreapi-0.0.3/src/spyre/crm.py +26 -0
  9. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/customers.py +1 -1
  10. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/sales.py +55 -2
  11. {spyreapi-0.0.2 → spyreapi-0.0.3/src/spyreapi.egg-info}/PKG-INFO +18 -1
  12. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyreapi.egg-info/SOURCES.txt +2 -2
  13. spyreapi-0.0.2/MANIFEST.in +0 -3
  14. spyreapi-0.0.2/tests/testing.py +0 -378
  15. {spyreapi-0.0.2 → spyreapi-0.0.3}/LICENSE +0 -0
  16. {spyreapi-0.0.2 → spyreapi-0.0.3}/setup.cfg +0 -0
  17. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Exceptions.py +0 -0
  18. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Models/__init__.py +0 -0
  19. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Models/customers_models.py +0 -0
  20. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/Models/inventory_models.py +0 -0
  21. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/__init__.py +0 -0
  22. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/config.py +0 -0
  23. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/inventory.py +0 -0
  24. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/spire.py +0 -0
  25. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyre/utils.py +0 -0
  26. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyreapi.egg-info/dependency_links.txt +0 -0
  27. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyreapi.egg-info/requires.txt +0 -0
  28. {spyreapi-0.0.2 → spyreapi-0.0.3}/src/spyreapi.egg-info/top_level.txt +0 -0
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ global-exclude *.pyc
4
+ global-exclude tests/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spyreapi
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A robust and extensible Python client for interacting with the [Spire Business Software API](https://developer.spiresystems.com/reference). This client provides an object-oriented interface to get, create, update, delete, query, filter, sort, and manage various Spire modules such as Sales Orders, Invoices, Inventory Items, and more.
5
5
  Author-email: Sanjid Sharaf <sanjidsharaf1@gmail.com>
6
6
  License-Expression: MIT
@@ -42,3 +42,20 @@ A robust and extensible Python client for interacting with the [Spire Business S
42
42
 
43
43
  ```bash
44
44
  pip install -r requirements.txt
45
+ ```
46
+
47
+ ---
48
+
49
+ ## ⚙️ Configuration
50
+
51
+ - Before using the client, set up your environment configuration:
52
+
53
+ ### Add your Base URL to your spire server to a `.env` file
54
+
55
+ - In your project root, create a `.env` file to securely store your Spire configuration.
56
+ - Add the following variable:
57
+
58
+ ```env
59
+ BASE_URL = https://{your-spire-domain}/api/v2/companies/
60
+ ```
61
+ - Replace {your-spire-domain} with your actual Spire server's hostname or IP address.
@@ -20,3 +20,20 @@ A robust and extensible Python client for interacting with the [Spire Business S
20
20
 
21
21
  ```bash
22
22
  pip install -r requirements.txt
23
+ ```
24
+
25
+ ---
26
+
27
+ ## ⚙️ Configuration
28
+
29
+ - Before using the client, set up your environment configuration:
30
+
31
+ ### Add your Base URL to your spire server to a `.env` file
32
+
33
+ - In your project root, create a `.env` file to securely store your Spire configuration.
34
+ - Add the following variable:
35
+
36
+ ```env
37
+ BASE_URL = https://{your-spire-domain}/api/v2/companies/
38
+ ```
39
+ - Replace {your-spire-domain} with your actual Spire server's hostname or IP address.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "spyreapi"
7
- version = "0.0.2"
7
+ version = "0.0.3"
8
8
  authors = [
9
9
  { name="Sanjid Sharaf", email="sanjidsharaf1@gmail.com" },
10
10
  ]
@@ -15,7 +15,7 @@ class SalesOrderItem(BaseModel):
15
15
  sequence: Optional[int] = None
16
16
  parentSequence: Optional[int] = None
17
17
  inventory: Optional[Inventory] = None
18
- serials: Optional[str] = None
18
+ serials: Optional[List[str]] = None
19
19
  whse: Optional[str] = None
20
20
  partNo: Optional[str] = None
21
21
  description: Optional[str] = None
@@ -1,4 +1,4 @@
1
- from typing import List, Optional, Dict, Union
1
+ from typing import List, Optional, Dict, Union, Any
2
2
  from pydantic import BaseModel, model_validator
3
3
 
4
4
  class PhoneFax(BaseModel):
@@ -94,3 +94,32 @@ class Address(BaseModel):
94
94
  if isinstance(contacts, list) and len(contacts) > 3:
95
95
  data['contacts'] = contacts[:3]
96
96
  return data
97
+
98
+ class AssignedTo(BaseModel):
99
+ id: Optional[int] = None
100
+ uuid: Optional[str] = None
101
+ username: Optional[str] = None
102
+
103
+ class Note(BaseModel):
104
+ id: Optional[int] = None
105
+ linkTable: Optional[str] = None
106
+ linkNo: Optional[str] = None
107
+ subject: Optional[str] = None
108
+ body: Optional[str] = None
109
+ attachment: Optional[Any] = None
110
+ attachmentName: Optional[str] = None
111
+ dueDate: Optional[str] = None
112
+ completedDate: Optional[str] = None
113
+ attention: Optional[str] = None
114
+ type: Optional[str] = None
115
+ displayType: Optional[str] = None
116
+ assignedTo: Optional[AssignedTo] = None
117
+ groupType: Optional[str] = None
118
+ qty: Optional[int] = None
119
+ alert: Optional[Union[str, bool]] = None
120
+ print: Optional[Union[str, bool]] = None
121
+ created: Optional[str] = None
122
+ createdBy: Optional[str] = None
123
+ modified: Optional[str] = None
124
+ modifiedBy: Optional[str] = None
125
+ links: Optional[Dict[str, str]] = None
@@ -116,8 +116,13 @@ class SpireClient():
116
116
 
117
117
  if query:
118
118
  params.append(("q", query))
119
-
119
+
120
120
  if filter:
121
+ model_fields = resource_cls.Model.model_fields.keys()
122
+ invalid_fields = [key for key in filter.keys() if key not in model_fields]
123
+ if invalid_fields:
124
+ raise ValueError(f"Invalid filter field(s): {invalid_fields}. for {resource_cls.Model.__name__} ")
125
+
121
126
  encoded_filter = json.dumps(filter)
122
127
  params.append(("filter", encoded_filter))
123
128
 
@@ -0,0 +1,26 @@
1
+ from .client import APIResource, SpireClient
2
+ from .Models.shared_models import Note
3
+
4
+ class CRMClient():
5
+
6
+ def __init__(self, client: SpireClient):
7
+ self.client = client
8
+ self.endpoint = "crm"
9
+
10
+ def get_note(self, id : int) -> "note":
11
+ """
12
+ Retrieve a note by its ID.
13
+
14
+ Args:
15
+ id (int): The ID of the note to retrieve.
16
+
17
+ Returns:
18
+ note: The retrieved note
19
+ """
20
+ response = self.client._get(f"/{self.endpoint}/notes/{str(id)}")
21
+ return note.from_json(response, self.client)
22
+
23
+
24
+ class note(APIResource[Note]):
25
+ endpoint = 'crm/notes'
26
+ Model = Note
@@ -83,7 +83,7 @@ class CustomerClient():
83
83
  return self.client._delete(f"/{self.endpoint}/{str(id)}")
84
84
 
85
85
 
86
- def query_invoices(
86
+ def query_customers (
87
87
  self,
88
88
  *,
89
89
  query: Optional[str] = None,
@@ -1,10 +1,12 @@
1
1
  from .client import APIResource
2
2
  from .Models.sales_models import SalesOrder, SalesOrderItem, Invoice
3
+ from .Models.shared_models import Note
3
4
  from .utils import *
4
5
  from .client import SpireClient
5
6
  from urllib.parse import urlparse
6
7
  from .Exceptions import CreateRequestError
7
8
  from typing import Any, Optional, List, Dict
9
+ from .crm import note, CRMClient
8
10
 
9
11
  class OrdersClient():
10
12
 
@@ -37,7 +39,7 @@ class OrdersClient():
37
39
  Sends a POST request to the sales order endpoint .
38
40
 
39
41
  Args:
40
- sales_order (dict): A SalesOrder instace containing the sales order details.
42
+ sales_order (dict): A SalesOrder instance containing the sales order details.
41
43
 
42
44
  Returns:
43
45
  salesOrder: The created SalesOrder instance.
@@ -129,6 +131,31 @@ class OrdersClient():
129
131
  **extra_params
130
132
  )
131
133
 
134
+ def create_sales_order_note(self, id: int , note_body : str, note_subject : str = "Note") -> note:
135
+ """
136
+ Create a new note on this sales order.
137
+
138
+ Args:
139
+ id (int): The id of the salesOrder to create a note on.
140
+ note (str): The body of the note
141
+ Returns:
142
+ note: The created note
143
+
144
+ Raises:
145
+ CreateRequestError: If the creation fails or response is invalid.
146
+ """
147
+
148
+ note_model = Note(body=note_body, subject=note_subject)
149
+ response = self.client._post(f"/{self.endpoint}/{id}/notes/", json=note_model.model_dump(exclude_unset=True, exclude_none=True))
150
+ if response.get('status_code') == 201:
151
+ location = response.get('headers').get('location')
152
+ parsed_url = urlparse(location)
153
+ path_segments = parsed_url.path.rstrip("/").split("/")
154
+ id = path_segments[-1]
155
+ return CRMClient(client=self.client).get_note(id)
156
+ else:
157
+ error_message = response.get('content')
158
+ raise CreateRequestError(self.endpoint, status_code=response.get('status_code'), error_message=error_message)
132
159
 
133
160
  class InvoiceClient():
134
161
 
@@ -277,6 +304,30 @@ class salesOrder(APIResource[SalesOrder]):
277
304
  response = self._client._put(f"/{self.endpoint}/{str(self.id)}", json=data)
278
305
  return salesOrder.from_json(response, self._client)
279
306
 
307
+ def add_note(self, note_body : "str" , note_subject : "str" = "Note") -> note:
308
+ """
309
+ Add a note to this sales order
310
+
311
+ Args:
312
+ note_body (str): the body of the note.
313
+ note_subject (str, "Note"): the subject of the note. the defualt value is just "Note"
314
+
315
+ Returns:
316
+ note: The note created.
317
+ """
318
+
319
+ note_model = Note(body=note_body, subject=note_subject)
320
+ response = self._client._post(f"/{self.endpoint}/{str(self.id)}/notes/", json=note_model.model_dump(exclude_unset=True, exclude_none=True))
321
+ if response.get('status_code') == 201:
322
+ location = response.get('headers').get('location')
323
+ parsed_url = urlparse(location)
324
+ path_segments = parsed_url.path.rstrip("/").split("/")
325
+ id = path_segments[-1]
326
+ return CRMClient(client=self._client).get_note(id)
327
+ else:
328
+ error_message = response.get('content')
329
+ raise CreateRequestError(f"/{self.endpoint}/{str(self.id)}/notes/", status_code=response.get('status_code'), error_message=error_message)
330
+
280
331
  class invoice(APIResource[Invoice]):
281
332
  endpoint = "sales/invoices/"
282
333
  Model = Invoice
@@ -310,4 +361,6 @@ class invoice(APIResource[Invoice]):
310
361
  """
311
362
  data = invoice_.model_dump(exclude_unset=True, exclude_none=True) if invoice_ else self.model_dump(exclude_unset=True, exclude_none=True)
312
363
  response = self._client._put(f"/{self.endpoint}/{str(self.id)}", json=data)
313
- return invoice.from_json(response, self._client)
364
+ return invoice.from_json(response, self._client)
365
+
366
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spyreapi
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A robust and extensible Python client for interacting with the [Spire Business Software API](https://developer.spiresystems.com/reference). This client provides an object-oriented interface to get, create, update, delete, query, filter, sort, and manage various Spire modules such as Sales Orders, Invoices, Inventory Items, and more.
5
5
  Author-email: Sanjid Sharaf <sanjidsharaf1@gmail.com>
6
6
  License-Expression: MIT
@@ -42,3 +42,20 @@ A robust and extensible Python client for interacting with the [Spire Business S
42
42
 
43
43
  ```bash
44
44
  pip install -r requirements.txt
45
+ ```
46
+
47
+ ---
48
+
49
+ ## ⚙️ Configuration
50
+
51
+ - Before using the client, set up your environment configuration:
52
+
53
+ ### Add your Base URL to your spire server to a `.env` file
54
+
55
+ - In your project root, create a `.env` file to securely store your Spire configuration.
56
+ - Add the following variable:
57
+
58
+ ```env
59
+ BASE_URL = https://{your-spire-domain}/api/v2/companies/
60
+ ```
61
+ - Replace {your-spire-domain} with your actual Spire server's hostname or IP address.
@@ -6,6 +6,7 @@ src/spyre/Exceptions.py
6
6
  src/spyre/__init__.py
7
7
  src/spyre/client.py
8
8
  src/spyre/config.py
9
+ src/spyre/crm.py
9
10
  src/spyre/customers.py
10
11
  src/spyre/inventory.py
11
12
  src/spyre/sales.py
@@ -20,5 +21,4 @@ src/spyreapi.egg-info/PKG-INFO
20
21
  src/spyreapi.egg-info/SOURCES.txt
21
22
  src/spyreapi.egg-info/dependency_links.txt
22
23
  src/spyreapi.egg-info/requires.txt
23
- src/spyreapi.egg-info/top_level.txt
24
- tests/testing.py
24
+ src/spyreapi.egg-info/top_level.txt
@@ -1,3 +0,0 @@
1
- include README.md
2
- include LICENSE
3
- global-exclude *.pyc
@@ -1,378 +0,0 @@
1
- import spyre
2
- import spyre.spire
3
-
4
- """
5
- Tested
6
- > Get Order
7
- > Pydantic Model
8
- > Creating Order
9
- > Deleting Order
10
- > Updating Order
11
- > Processing a order
12
- > Invoicing a order
13
- > Reversing a invoice(Check with eric)
14
- > Get Invoice
15
- > Update Invoice
16
- > Get Customer
17
- > Create Customer
18
- > Update Customer
19
- > Delete Customer
20
- > Querying
21
- > Filtering
22
- > Sorting
23
-
24
-
25
- Todo
26
-
27
-
28
- >Exceptions (Duplicate , Processing quotes, Invalid inPuts)
29
- >Documentation
30
- >Response handling/ object -> Replace Riase_for_status
31
- >Invoice Items/ Sales Order Item
32
- >Payments, Deposit on Sales Order
33
- >get by orderNo/invoiceNo etc
34
-
35
- # >Querying
36
- # >filtering and sorting
37
- # >Create returns the item created
38
- # >Customer
39
- # >Make Wrapper class and implemement Oob type classes & methods
40
- # >Create a model for Orders
41
- # >Test Create,Update,
42
- # >Processing Orders
43
- # >Cancel/Delete
44
- # >Return
45
- """
46
-
47
-
48
- spire = Spire('intertest' , 'david1' , 'david')
49
-
50
-
51
-
52
-
53
- order = spire.orders.get_sales_order(51247)
54
- order.model.location = "01"
55
- print(order.update())
56
-
57
- # order = spire.orders.get_sales_order(51245)
58
- # print(order.invoice())
59
-
60
- TAXES = {
61
- 0.05 : 1,
62
-
63
- 0.08 : 2,
64
- 0.13 : 3,
65
- 0.15 : 4,
66
- 0.14 : 5,
67
- 0.12 : 6,
68
- 0.11 : 7
69
- }
70
-
71
- order = {
72
- "amazon-order-id": "702-6212155-2707463",
73
- "merchant-order-id": "3045",
74
- "purchase-date": "5/31/2025 23:22",
75
- "last-updated-date": "6/2/2025 11:08",
76
- "order-status": "Shipped",
77
- "fulfillment-channel": "Merchant",
78
- "sales-channel": "Amazon.ca",
79
- "order-channel": "WebsiteOrderChannel",
80
- "url": "",
81
- "ship-service-level": "Standard",
82
- "product-name": "20V MAX 1/2IN Compact Impact WR- HR",
83
- "sku": "DEWDCF921B",
84
- "asin": "B09M3TL9BB",
85
- "number-of-items": 1,
86
- "item-status": "Shipped",
87
- "tax-collection-model": "",
88
- "tax-collection-responsible-party": "",
89
- "quantity": 1,
90
- "currency": "CAD",
91
- "item-price": 195,
92
- "item-tax": 21.45,
93
- "shipping-price": "",
94
- "shipping-tax": "",
95
- "gift-wrap-price": "",
96
- "gift-wrap-tax": "",
97
- "item-promotion-discount": "",
98
- "ship-promotion-discount": "",
99
- "address-type": "",
100
- "ship-city": "Maple Creek",
101
- "ship-state": "Saskatchewan",
102
- "ship-postal-code": "S0N 1N0",
103
- "ship-country": "CA",
104
- "promotion-ids": "",
105
- "is-business-order": False,
106
- "purchase-order-number": "",
107
- "price-designation": "",
108
- "fulfilled-by": "",
109
- "default-ship-from-address-name": "Interline Wholesale Hardware Distributors North",
110
- "default-ship-from-address-field-1": "399 Confederation Parkway",
111
- "default-ship-from-address-field-2": "",
112
- "default-ship-from-address-field-3": "",
113
- "default-ship-from-city": "Vaughan",
114
- "default-ship-from-state": "Ontario",
115
- "default-ship-from-country": "CA",
116
- "default-ship-from-postal-code": "L4K 4S1",
117
- "actual-ship-from-address-name": "Interline Wholesale Hardware Distributors North",
118
- "actual-ship-from-address-field-1": "399 Confederation Parkway",
119
- "actual-ship-from-address-field-2": "",
120
- "actual-ship-from-address-field-3": "",
121
- "actual-ship-from-city": "Vaughan",
122
- "actual-ship-from-state": "Ontario",
123
- "actual-ship-from-country": "CA",
124
- "actual-ship-from-postal-code": "L4K 4S1",
125
- "serial-numbers": ""
126
- }
127
-
128
- from datetime import datetime
129
-
130
- def convert_order_date(date_str: str) -> str:
131
- try:
132
- dt = datetime.strptime(date_str, "%m/%d/%Y %H:%M")
133
- return dt.strftime("%Y-%m-%d")
134
- except ValueError:
135
- return ""
136
-
137
-
138
- def get_tax_code(order: dict) -> int:
139
- try:
140
- item_price = float(order.get('item-price', 0))
141
- item_tax = float(order.get('item-tax', 0))
142
-
143
- if item_price == 0:
144
- raise ValueError("Item price cannot be zero.")
145
-
146
- tax_rate = item_tax / item_price
147
- print(tax_rate)
148
- # Find the closest tax rate key
149
- closest_rate = min(TAXES.keys(), key=lambda r: abs(r - tax_rate))
150
- print(closest_rate)
151
- return TAXES[closest_rate]
152
-
153
- except (TypeError, ValueError):
154
- return None # or raise an error if preferred
155
-
156
-
157
- def convert_order_to_sales_order(order: dict) -> SalesOrder:
158
-
159
- amazn_id = order.get('amazon-order-id')
160
- udf = {
161
- "shopid" : amazn_id,
162
- "shipped" : order.get('order-status') == 'shipped'
163
- }
164
-
165
- status = "O"
166
- # if order.get('order-status') == 'shipped':
167
- # status = "H"
168
-
169
- tax_code = get_tax_code(order)
170
-
171
- shipping_address = Address(city=order.get('ship-city'), provState= order.get('ship-state'), postalCode = order.get('ship-postal-code'), country=order.get('ship-country'),
172
- salesTaxes=[ { "code" : tax_code } ]
173
- )
174
-
175
- items = []
176
- item = SalesOrderItem(
177
- inventory=Inventory(partNo=order.get("sku"), whse='00'),
178
- partNo=order.get("sku"),
179
- orderQty=str(order.get("quantity")),
180
- unitPrice=str( float(order.get("item-price")) /float(order.get("quantity")) ),
181
- taxFlags= [True,True,True,True],
182
- committedQty=str(order.get("quantity")),
183
-
184
- )
185
-
186
- items.append(item)
187
- freight = str(
188
- float(order.get('shipping-tax', '0') or 0) -
189
- float(order.get('ship-promotion-discount', '0') or 0)
190
- )
191
-
192
- customer = Customer(customerNo="AMAZON")
193
-
194
- return SalesOrder(
195
- orderNo= "AMZN3" + amazn_id[-5:] ,
196
- orderDate=convert_order_date(order.get("purchase-date")),
197
- type = "O",
198
- referenceNo= amazn_id,
199
- status=status,
200
- currency=Currency(code=order.get("currency")) if order.get("currency") else None,
201
- shippingAddress=shipping_address,
202
- items=items,
203
- udf=udf,
204
- freight=freight,
205
- customer=customer,
206
-
207
- )
208
-
209
- sales_order = convert_order_to_sales_order(order)
210
- print(sales_order.model_dump_json(indent=2 , exclude_none= True))
211
-
212
-
213
-
214
- # order.model.payments = [ {"method" : "06" , "amount" : "216.45" , "layawayFlag" : False}]
215
- # order.update()
216
- # print(order.invoice())
217
-
218
-
219
-
220
- # uoms = spire.inventory.items.get_item_uoms(id = 811)
221
- # test_uom = uoms[2]
222
- # print(test_uom.description)
223
-
224
-
225
- # inv = spire.invoices.get_invoice(206363)
226
- # order_converted.
227
- # order_converted = create_sales_order_from_invoice(inv.model)
228
- # print(order_converted.model_dump_json(exclude_none=True, exclude_unset=True, indent=2))
229
-
230
-
231
- # cust = spire.customers.get_customer(1)
232
-
233
- # ord = spire.orders.get_sales_order(31319)
234
- # ord.customer = cust.model
235
-
236
- # print(ord.update())
237
-
238
-
239
- # order_test = json.loads("""
240
-
241
- # {
242
- # "customer": {
243
- # "id" : 3143
244
- # },
245
- # "currency": {
246
- # "code": "CAD"
247
-
248
- # },
249
- # "address": {
250
- # "country": "Can",
251
- # "defaultWarehouse": "00",
252
- # "line1": "629 Daintry Crescent",
253
- # "line2": "Cobourg ON K9A 4X9",
254
- # "email": "beatty731@yahoo.com",
255
- # "contacts": [
256
- # {
257
- # "phone": {
258
- # "number": "+1 905-207-1116"
259
- # }
260
- # }
261
- # ]
262
- # },
263
- # "contact": {
264
- # "phone": {
265
- # "number": "+1 905-207-1116"
266
- # },
267
- # "name": "safdasd"
268
- # },
269
- # "shippingCarrier": "1",
270
- # "referenceNo": "1",
271
- # "trackingNo": "1",
272
- # "shipDate": null,
273
- # "items": [
274
- # {
275
- # "inventory": {
276
- # "id": 12345,
277
- # "whse": "00"
278
- # }
279
- # }
280
- # ],
281
- # "freight": "1",
282
- # "discount": "1",
283
- # "surcharge": "1",
284
- # "status": "O",
285
- # "type": "Q",
286
- # "hold": false,
287
- # "customerPO": "1"
288
- # }
289
-
290
- # """)
291
-
292
-
293
-
294
- # order = SalesOrder(**order_test)
295
- # print(order.model_dump(exclude_unset=True, ))
296
-
297
-
298
-
299
- # spire.orders.get_sales_order
300
- # invoice_test = spire.invoices.get_invoice(206362)
301
- # response = invoice_test.reverse()
302
- # print(response)
303
-
304
- # order = spire.orders.get_sales_order(31312)
305
- # response = order.invoice()
306
-
307
- # response = order.update_sales_order
308
-
309
- # order = spire.orders.get_sales_order(31307)
310
- # response = order.delete()
311
- # print(response)
312
-
313
- # resp = spire.orders.delete_sales_order(31306)
314
- # print(resp)
315
-
316
-
317
-
318
- # response = spire.orders.create_sales_order(order_test)
319
- # print(response)
320
-
321
-
322
-
323
- # orders_client = OrdersClient(client)
324
- # order = orders_client.get_order(12334)
325
- # order.invoice()
326
-
327
-
328
- # invoice_client = InvoiceClient(client)
329
-
330
- # response = invoice_client.reverse_invoice(206354)
331
- # print(response)
332
-
333
- # invoice_em = invoice_client.get_invoice(206355)
334
- # invoice_model = Invoice(**invoice_em)
335
-
336
- # print(invoice_model.model_dump_json(indent=2))
337
-
338
- # order_converted = create_sales_order_from_invoice(invoice_model)
339
- # print(order_converted.model_dump_json(indent=2, exclude_unset=True, exclude_none=True))
340
-
341
- # response = orders_client.create_order(order_converted.model_dump(exclude_unset=True, exclude_none=True))
342
- # print(response)
343
-
344
-
345
- # Get an order by ID
346
- # order_1001 = orders_client.get_order(1001)
347
- # try:
348
- # orderModel = SalesOrder(**order_1001)
349
- # except Exception as e:
350
- # print(e.errors())
351
-
352
- # print(order)
353
- # print(orderModel.model_dump_json(indent=2))
354
-
355
- #Create an ORder
356
-
357
-
358
-
359
- # response = orders_client.create_order(order_test)
360
- # print(response)
361
-
362
- # deleting An order
363
- # response = orders_client.delete_order(31299)
364
- # print(response)
365
-
366
- # Updating an order
367
- # orderModel.location = "01"
368
- # print(orderModel.model_dump_json(indent=2))
369
-
370
- # response = orders_client.update_order(1001, orderModel.model_dump_json())
371
- # print(response)
372
-
373
-
374
- # order_test_model = SalesOrder(**order_test)
375
- # print(order_test_model.model_dump(exclude_none=True))
376
-
377
-
378
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes