prestashop-webservice 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prestashop_webservice/__init__.py +82 -0
- prestashop_webservice/address.py +29 -0
- prestashop_webservice/base_model.py +121 -0
- prestashop_webservice/carrier.py +31 -0
- prestashop_webservice/client.py +160 -0
- prestashop_webservice/combination.py +29 -0
- prestashop_webservice/config.py +9 -0
- prestashop_webservice/country.py +30 -0
- prestashop_webservice/customer.py +42 -0
- prestashop_webservice/customer_message.py +29 -0
- prestashop_webservice/customer_thread.py +23 -0
- prestashop_webservice/image_product.py +12 -0
- prestashop_webservice/logger.py +31 -0
- prestashop_webservice/models.py +448 -0
- prestashop_webservice/order.py +114 -0
- prestashop_webservice/order_carrier.py +33 -0
- prestashop_webservice/order_detail.py +28 -0
- prestashop_webservice/order_history.py +57 -0
- prestashop_webservice/order_state.py +12 -0
- prestashop_webservice/params.py +77 -0
- prestashop_webservice/product.py +54 -0
- prestashop_webservice/py.typed +2 -0
- prestashop_webservice/state.py +12 -0
- prestashop_webservice-0.3.0.dist-info/METADATA +97 -0
- prestashop_webservice-0.3.0.dist-info/RECORD +28 -0
- prestashop_webservice-0.3.0.dist-info/WHEEL +5 -0
- prestashop_webservice-0.3.0.dist-info/licenses/LICENSE +21 -0
- prestashop_webservice-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class OrderData:
|
|
7
|
+
"""Order resource data."""
|
|
8
|
+
|
|
9
|
+
id: int
|
|
10
|
+
# Core fields
|
|
11
|
+
id_customer: int | None = None
|
|
12
|
+
id_cart: int | None = None
|
|
13
|
+
id_currency: int | None = None
|
|
14
|
+
id_lang: int | None = None
|
|
15
|
+
id_address_delivery: int | None = None
|
|
16
|
+
id_address_invoice: int | None = None
|
|
17
|
+
id_carrier: int | None = None
|
|
18
|
+
id_shop: int | None = None
|
|
19
|
+
id_shop_group: int | None = None
|
|
20
|
+
current_state: int | None = None
|
|
21
|
+
reference: str | None = None
|
|
22
|
+
secure_key: str | None = None
|
|
23
|
+
payment: str | None = None
|
|
24
|
+
module: str | None = None
|
|
25
|
+
# Totals
|
|
26
|
+
total_paid: str | None = None
|
|
27
|
+
total_paid_tax_incl: str | None = None
|
|
28
|
+
total_paid_tax_excl: str | None = None
|
|
29
|
+
total_paid_real: str | None = None
|
|
30
|
+
total_products: str | None = None
|
|
31
|
+
total_products_wt: str | None = None
|
|
32
|
+
total_shipping: str | None = None
|
|
33
|
+
total_shipping_tax_incl: str | None = None
|
|
34
|
+
total_shipping_tax_excl: str | None = None
|
|
35
|
+
total_discounts: str | None = None
|
|
36
|
+
total_discounts_tax_incl: str | None = None
|
|
37
|
+
total_discounts_tax_excl: str | None = None
|
|
38
|
+
total_wrapping: str | None = None
|
|
39
|
+
total_wrapping_tax_incl: str | None = None
|
|
40
|
+
total_wrapping_tax_excl: str | None = None
|
|
41
|
+
# Other fields
|
|
42
|
+
carrier_tax_rate: str | None = None
|
|
43
|
+
conversion_rate: str | None = None
|
|
44
|
+
round_mode: int | None = None
|
|
45
|
+
round_type: int | None = None
|
|
46
|
+
invoice_number: str | None = None
|
|
47
|
+
invoice_date: str | None = None
|
|
48
|
+
delivery_number: str | None = None
|
|
49
|
+
delivery_date: str | None = None
|
|
50
|
+
shipping_number: str | None = None
|
|
51
|
+
note: str | None = None
|
|
52
|
+
valid: int | None = None
|
|
53
|
+
date_add: str | None = None
|
|
54
|
+
date_upd: str | None = None
|
|
55
|
+
associations: dict[str, Any] | None = None
|
|
56
|
+
|
|
57
|
+
def __post_init__(self, **kwargs):
|
|
58
|
+
"""Ignore extra fields from API."""
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class CustomerData:
|
|
64
|
+
"""Customer resource data."""
|
|
65
|
+
|
|
66
|
+
id: int
|
|
67
|
+
# Core fields
|
|
68
|
+
id_default_group: int | None = None
|
|
69
|
+
id_lang: int | None = None
|
|
70
|
+
id_shop: int | None = None
|
|
71
|
+
id_shop_group: int | None = None
|
|
72
|
+
email: str | None = None
|
|
73
|
+
firstname: str | None = None
|
|
74
|
+
lastname: str | None = None
|
|
75
|
+
active: int | None = None
|
|
76
|
+
date_add: str | None = None
|
|
77
|
+
date_upd: str | None = None
|
|
78
|
+
# Optional fields
|
|
79
|
+
id_gender: int | None = None
|
|
80
|
+
birthday: str | None = None
|
|
81
|
+
newsletter: int | None = None
|
|
82
|
+
optin: int | None = None
|
|
83
|
+
website: str | None = None
|
|
84
|
+
company: str | None = None
|
|
85
|
+
siret: str | None = None
|
|
86
|
+
ape: str | None = None
|
|
87
|
+
outstanding_allow_amount: str | None = None
|
|
88
|
+
max_payment_days: int | None = None
|
|
89
|
+
note: str | None = None
|
|
90
|
+
secure_key: str | None = None
|
|
91
|
+
# Extra fields from API
|
|
92
|
+
passwd: str | None = None
|
|
93
|
+
last_passwd_gen: str | None = None
|
|
94
|
+
newsletter_date_add: str | None = None
|
|
95
|
+
reset_password_validity: str | None = None
|
|
96
|
+
associations: dict[str, Any] | None = None
|
|
97
|
+
|
|
98
|
+
def __post_init__(self, **kwargs):
|
|
99
|
+
"""Ignore extra fields from API."""
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass
|
|
104
|
+
class ProductData:
|
|
105
|
+
"""Product resource data."""
|
|
106
|
+
|
|
107
|
+
id: int
|
|
108
|
+
# Core fields
|
|
109
|
+
id_manufacturer: int | None = None
|
|
110
|
+
id_supplier: int | None = None
|
|
111
|
+
id_category_default: int | None = None
|
|
112
|
+
id_shop_default: int | None = None
|
|
113
|
+
id_tax_rules_group: int | None = None
|
|
114
|
+
id_default_image: int | None = None # Default product image
|
|
115
|
+
id_default_combination: int | None = None # Default product combination
|
|
116
|
+
reference: str | None = None
|
|
117
|
+
name: str | None = None
|
|
118
|
+
manufacturer_name: str | None = None
|
|
119
|
+
price: str | None = None
|
|
120
|
+
active: int | None = None
|
|
121
|
+
date_add: str | None = None
|
|
122
|
+
date_upd: str | None = None
|
|
123
|
+
# Optional fields
|
|
124
|
+
ean13: str | None = None
|
|
125
|
+
isbn: str | None = None
|
|
126
|
+
upc: str | None = None
|
|
127
|
+
mpn: str | None = None
|
|
128
|
+
supplier_reference: str | None = None
|
|
129
|
+
location: str | None = None
|
|
130
|
+
width: str | None = None
|
|
131
|
+
height: str | None = None
|
|
132
|
+
depth: str | None = None
|
|
133
|
+
weight: str | None = None
|
|
134
|
+
quantity: int | None = None
|
|
135
|
+
description: str | None = None
|
|
136
|
+
description_short: str | None = None
|
|
137
|
+
available_for_order: int | None = None
|
|
138
|
+
condition: str | None = None
|
|
139
|
+
show_price: int | None = None
|
|
140
|
+
indexed: int | None = None
|
|
141
|
+
visibility: str | None = None
|
|
142
|
+
cache_default_attribute: int | None = None
|
|
143
|
+
advanced_stock_management: int | None = None
|
|
144
|
+
available_date: str | None = None
|
|
145
|
+
type: str | None = None
|
|
146
|
+
state: int | None = None
|
|
147
|
+
# Extra fields from API
|
|
148
|
+
additional_shipping_cost: str | None = None
|
|
149
|
+
ecotax: str | None = None
|
|
150
|
+
link_rewrite: str | None = None
|
|
151
|
+
meta_description: str | None = None
|
|
152
|
+
meta_title: str | None = None # Meta title for SEO
|
|
153
|
+
minimal_quantity: int | None = None # Minimum purchase quantity
|
|
154
|
+
pack_stock_type: int | None = None # Stock type for packs
|
|
155
|
+
position_in_category: int | None = None
|
|
156
|
+
product_type: str | None = None
|
|
157
|
+
redirect_type: str | None = None # Redirect type (404, etc)
|
|
158
|
+
unit_price: str | None = None
|
|
159
|
+
unit_price_ratio: str | None = None
|
|
160
|
+
wholesale_price: str | None = None
|
|
161
|
+
additional_delivery_times: int | None = None # Delivery times option
|
|
162
|
+
associations: dict[str, Any] | None = None
|
|
163
|
+
cache_is_pack: int | None = None
|
|
164
|
+
low_stock_threshold: int | None = None
|
|
165
|
+
unity: str | None = None
|
|
166
|
+
|
|
167
|
+
def __post_init__(self, **kwargs):
|
|
168
|
+
"""Ignore extra fields from API."""
|
|
169
|
+
pass
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@dataclass
|
|
173
|
+
class AddressData:
|
|
174
|
+
"""Address resource data."""
|
|
175
|
+
|
|
176
|
+
id: int
|
|
177
|
+
# All fields optional except id
|
|
178
|
+
id_customer: int | None = None
|
|
179
|
+
id_country: int | None = None
|
|
180
|
+
alias: str | None = None
|
|
181
|
+
lastname: str | None = None
|
|
182
|
+
firstname: str | None = None
|
|
183
|
+
address1: str | None = None
|
|
184
|
+
city: str | None = None
|
|
185
|
+
postcode: str | None = None
|
|
186
|
+
date_add: str | None = None
|
|
187
|
+
date_upd: str | None = None
|
|
188
|
+
id_manufacturer: int | None = None
|
|
189
|
+
id_supplier: int | None = None
|
|
190
|
+
id_warehouse: int | None = None
|
|
191
|
+
id_state: int | None = None
|
|
192
|
+
company: str | None = None
|
|
193
|
+
vat_number: str | None = None
|
|
194
|
+
address2: str | None = None
|
|
195
|
+
phone: str | None = None
|
|
196
|
+
phone_mobile: str | None = None
|
|
197
|
+
dni: str | None = None
|
|
198
|
+
deleted: int | None = None
|
|
199
|
+
other: str | None = None
|
|
200
|
+
|
|
201
|
+
def __post_init__(self, **kwargs):
|
|
202
|
+
"""Ignore extra fields from API."""
|
|
203
|
+
pass
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@dataclass
|
|
207
|
+
class CountryData:
|
|
208
|
+
"""Country resource data."""
|
|
209
|
+
|
|
210
|
+
id: int
|
|
211
|
+
# All fields optional except id
|
|
212
|
+
id_zone: int | None = None
|
|
213
|
+
iso_code: str | None = None
|
|
214
|
+
name: str | None = None
|
|
215
|
+
active: int | None = None
|
|
216
|
+
call_prefix: int | None = None
|
|
217
|
+
contains_states: int | None = None
|
|
218
|
+
need_identification_number: int | None = None
|
|
219
|
+
need_zip_code: int | None = None
|
|
220
|
+
zip_code_format: str | None = None
|
|
221
|
+
display_tax_label: int | None = None
|
|
222
|
+
id_currency: int | None = None
|
|
223
|
+
|
|
224
|
+
def __post_init__(self, **kwargs):
|
|
225
|
+
"""Ignore extra fields from API."""
|
|
226
|
+
pass
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@dataclass
|
|
230
|
+
class CarrierData:
|
|
231
|
+
"""Carrier resource data."""
|
|
232
|
+
|
|
233
|
+
id: int
|
|
234
|
+
deleted: int | None = None
|
|
235
|
+
is_module: int | None = None
|
|
236
|
+
id_tax_rules_group: int | None = None
|
|
237
|
+
id_reference: int | None = None
|
|
238
|
+
name: str | None = None
|
|
239
|
+
active: int | None = None
|
|
240
|
+
is_free: int | None = None
|
|
241
|
+
url: str | None = None
|
|
242
|
+
shipping_handling: int | None = None
|
|
243
|
+
shipping_external: int | None = None
|
|
244
|
+
range_behavior: int | None = None
|
|
245
|
+
shipping_method: int | None = None
|
|
246
|
+
max_width: int | None = None
|
|
247
|
+
max_height: int | None = None
|
|
248
|
+
max_depth: int | None = None
|
|
249
|
+
max_weight: str | None = None
|
|
250
|
+
grade: int | None = None
|
|
251
|
+
external_module_name: str | None = None
|
|
252
|
+
need_range: int | None = None
|
|
253
|
+
position: int | None = None
|
|
254
|
+
delay: str | dict[str, Any] | None = None
|
|
255
|
+
|
|
256
|
+
def __post_init__(self, **kwargs):
|
|
257
|
+
"""Ignore extra fields from API."""
|
|
258
|
+
pass
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@dataclass
|
|
262
|
+
class OrderCarrierData:
|
|
263
|
+
"""Order carrier resource data."""
|
|
264
|
+
|
|
265
|
+
id: int
|
|
266
|
+
# All fields optional except id
|
|
267
|
+
id_order: int | None = None
|
|
268
|
+
id_carrier: int | None = None
|
|
269
|
+
id_order_invoice: int | None = None
|
|
270
|
+
weight: str | None = None
|
|
271
|
+
shipping_cost_tax_excl: str | None = None
|
|
272
|
+
shipping_cost_tax_incl: str | None = None
|
|
273
|
+
tracking_number: str | None = None
|
|
274
|
+
date_add: str | None = None
|
|
275
|
+
|
|
276
|
+
def __post_init__(self, **kwargs):
|
|
277
|
+
"""Ignore extra fields from API."""
|
|
278
|
+
pass
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@dataclass
|
|
282
|
+
class OrderHistoryData:
|
|
283
|
+
"""Order history resource data."""
|
|
284
|
+
|
|
285
|
+
id: int
|
|
286
|
+
# All fields optional except id
|
|
287
|
+
id_order: int | None = None
|
|
288
|
+
id_order_state: int | None = None
|
|
289
|
+
id_employee: int | None = None
|
|
290
|
+
date_add: str | None = None
|
|
291
|
+
|
|
292
|
+
def __post_init__(self, **kwargs):
|
|
293
|
+
"""Ignore extra fields from API."""
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@dataclass
|
|
298
|
+
class OrderStateData:
|
|
299
|
+
"""Order state resource data."""
|
|
300
|
+
|
|
301
|
+
id: int
|
|
302
|
+
# All fields optional except id
|
|
303
|
+
name: str | None = None
|
|
304
|
+
color: str | None = None
|
|
305
|
+
unremovable: int | None = None
|
|
306
|
+
send_email: int | None = None
|
|
307
|
+
module_name: str | None = None
|
|
308
|
+
invoice: int | None = None
|
|
309
|
+
# Extra from API
|
|
310
|
+
template: str | None = None
|
|
311
|
+
# Fields that may not come
|
|
312
|
+
deleted: int | None = None
|
|
313
|
+
delivery: int | None = None
|
|
314
|
+
hidden: int | None = None
|
|
315
|
+
logable: int | None = None
|
|
316
|
+
paid: int | None = None
|
|
317
|
+
pdf_delivery: int | None = None
|
|
318
|
+
pdf_invoice: int | None = None
|
|
319
|
+
shipped: int | None = None
|
|
320
|
+
|
|
321
|
+
def __post_init__(self, **kwargs):
|
|
322
|
+
"""Ignore extra fields from API."""
|
|
323
|
+
pass
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
@dataclass
|
|
327
|
+
class StateData:
|
|
328
|
+
"""State/Province resource data."""
|
|
329
|
+
|
|
330
|
+
id: int
|
|
331
|
+
# All fields optional except id
|
|
332
|
+
id_country: int | None = None
|
|
333
|
+
id_zone: int | None = None
|
|
334
|
+
name: str | None = None
|
|
335
|
+
iso_code: str | None = None
|
|
336
|
+
active: int | None = None
|
|
337
|
+
|
|
338
|
+
def __post_init__(self, **kwargs):
|
|
339
|
+
"""Ignore extra fields from API."""
|
|
340
|
+
pass
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
@dataclass
|
|
344
|
+
class ImageProductData:
|
|
345
|
+
"""Product image resource data."""
|
|
346
|
+
|
|
347
|
+
id: int
|
|
348
|
+
# All fields optional except id
|
|
349
|
+
id_product: int | None = None
|
|
350
|
+
position: int | None = None
|
|
351
|
+
cover: int | None = None
|
|
352
|
+
legend: str | None = None
|
|
353
|
+
|
|
354
|
+
def __post_init__(self, **kwargs):
|
|
355
|
+
"""Ignore extra fields from API."""
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@dataclass
|
|
360
|
+
class CombinationData:
|
|
361
|
+
"""Combination resource data."""
|
|
362
|
+
|
|
363
|
+
id: int
|
|
364
|
+
# All fields optional except id
|
|
365
|
+
id_product: int | None = None
|
|
366
|
+
ean13: str | None = None
|
|
367
|
+
reference: str | None = None
|
|
368
|
+
wholesale_price: str | None = None
|
|
369
|
+
price: str | None = None
|
|
370
|
+
ecotax: str | None = None
|
|
371
|
+
weight: str | None = None
|
|
372
|
+
unit_price_impact: str | None = None
|
|
373
|
+
minimal_quantity: int | None = None
|
|
374
|
+
low_stock_threshold: int | None = None
|
|
375
|
+
default_on: int | None = None
|
|
376
|
+
available_date: str | None = None
|
|
377
|
+
associations: dict[str, Any] | None = None
|
|
378
|
+
|
|
379
|
+
def __post_init__(self, **kwargs):
|
|
380
|
+
"""Ignore extra fields from API."""
|
|
381
|
+
pass
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
@dataclass
|
|
385
|
+
class CustomerMessageData:
|
|
386
|
+
"""Customer message resource data."""
|
|
387
|
+
|
|
388
|
+
id: int
|
|
389
|
+
id_customer_thread: int | None = None
|
|
390
|
+
id_employee: int | None = None
|
|
391
|
+
message: str | None = None
|
|
392
|
+
file_name: str | None = None
|
|
393
|
+
ip_address: str | None = None
|
|
394
|
+
user_agent: str | None = None
|
|
395
|
+
date_add: str | None = None
|
|
396
|
+
date_upd: str | None = None
|
|
397
|
+
private: int | None = None
|
|
398
|
+
read: int | None = None
|
|
399
|
+
|
|
400
|
+
def __post_init__(self, **kwargs):
|
|
401
|
+
"""Ignore extra fields from API."""
|
|
402
|
+
pass
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@dataclass
|
|
406
|
+
class OrderDetailData:
|
|
407
|
+
"""Order detail resource data."""
|
|
408
|
+
|
|
409
|
+
id: int
|
|
410
|
+
id_order: int | None = None
|
|
411
|
+
product_id: int | None = None
|
|
412
|
+
product_attribute_id: int | None = None
|
|
413
|
+
product_name: str | None = None
|
|
414
|
+
product_quantity: int | None = None
|
|
415
|
+
product_price: str | None = None
|
|
416
|
+
product_reference: str | None = None
|
|
417
|
+
total_price_tax_incl: str | None = None
|
|
418
|
+
total_price_tax_excl: str | None = None
|
|
419
|
+
unit_price_tax_incl: str | None = None
|
|
420
|
+
unit_price_tax_excl: str | None = None
|
|
421
|
+
original_product_price: str | None = None
|
|
422
|
+
|
|
423
|
+
def __post_init__(self, **kwargs):
|
|
424
|
+
"""Ignore extra fields from API."""
|
|
425
|
+
pass
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
@dataclass
|
|
429
|
+
class CustomerThreadData:
|
|
430
|
+
"""Customer thread resource data."""
|
|
431
|
+
|
|
432
|
+
id: int
|
|
433
|
+
id_shop: int | None = None
|
|
434
|
+
id_lang: int | None = None
|
|
435
|
+
id_contact: int | None = None
|
|
436
|
+
id_customer: int | None = None
|
|
437
|
+
id_order: int | None = None
|
|
438
|
+
id_product: int | None = None
|
|
439
|
+
status: str | None = None
|
|
440
|
+
email: str | None = None
|
|
441
|
+
token: str | None = None
|
|
442
|
+
date_add: str | None = None
|
|
443
|
+
date_upd: str | None = None
|
|
444
|
+
associations: dict[str, Any] | None = None
|
|
445
|
+
|
|
446
|
+
def __post_init__(self, **kwargs):
|
|
447
|
+
"""Ignore extra fields from API."""
|
|
448
|
+
pass
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from prestashop_webservice.base_model import BaseModel
|
|
2
|
+
from prestashop_webservice.models import OrderData
|
|
3
|
+
from prestashop_webservice.params import Params
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Order(BaseModel):
|
|
7
|
+
"""Complex queries for orders endpoint."""
|
|
8
|
+
|
|
9
|
+
_data_class = OrderData
|
|
10
|
+
|
|
11
|
+
def get_by_id(self, order_id: str) -> OrderData:
|
|
12
|
+
"""Get order by ID."""
|
|
13
|
+
return self._query(f"orders/{order_id}", None, "order")
|
|
14
|
+
|
|
15
|
+
def exists(self, order_id: str) -> bool:
|
|
16
|
+
"""Check if order exists by ID."""
|
|
17
|
+
try:
|
|
18
|
+
self.get_by_id(order_id)
|
|
19
|
+
return True
|
|
20
|
+
except Exception:
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
def get_by_reference(self, reference: str) -> OrderData | None:
|
|
24
|
+
"""Get order by reference."""
|
|
25
|
+
params = Params(
|
|
26
|
+
filter={"reference": reference},
|
|
27
|
+
display=["id", "reference", "total_paid", "current_state", "id_customer"],
|
|
28
|
+
)
|
|
29
|
+
orders: list[OrderData] = self._query("orders", params, "orders")
|
|
30
|
+
return orders[0] if orders else None
|
|
31
|
+
|
|
32
|
+
def get_by_customer(self, customer_id: str, limit: int = 999) -> list[OrderData]:
|
|
33
|
+
"""Get all orders for a customer."""
|
|
34
|
+
params = Params(
|
|
35
|
+
filter={"id_customer": customer_id},
|
|
36
|
+
display=["id", "id_customer", "date_add", "total_paid", "reference"],
|
|
37
|
+
limit=limit,
|
|
38
|
+
)
|
|
39
|
+
return self._query("orders", params, "orders")
|
|
40
|
+
|
|
41
|
+
def get_latest_by_customer(self, customer_id: str) -> OrderData | None:
|
|
42
|
+
"""Get the most recent order for a customer."""
|
|
43
|
+
params = Params(
|
|
44
|
+
filter={"id_customer": customer_id},
|
|
45
|
+
display=["id", "id_customer", "date_add", "total_paid", "reference"],
|
|
46
|
+
limit=1,
|
|
47
|
+
)
|
|
48
|
+
orders: list[OrderData] = self._query("orders", params, "orders")
|
|
49
|
+
return orders[0] if orders else None
|
|
50
|
+
|
|
51
|
+
def get_recent(self, limit: int = 10) -> list[OrderData]:
|
|
52
|
+
"""Get recent orders."""
|
|
53
|
+
params = Params(
|
|
54
|
+
display=["id", "reference", "total_paid", "date_add", "id_customer"],
|
|
55
|
+
limit=limit,
|
|
56
|
+
)
|
|
57
|
+
return self._query("orders", params, "orders") # type: ignore
|
|
58
|
+
|
|
59
|
+
def get_by_status(self, status_id: str, limit: int = 100) -> list[OrderData]:
|
|
60
|
+
"""Get orders by status."""
|
|
61
|
+
params = Params(
|
|
62
|
+
filter={"current_state": status_id},
|
|
63
|
+
display=["id", "current_state", "reference", "date_add"],
|
|
64
|
+
limit=limit,
|
|
65
|
+
)
|
|
66
|
+
return self._query("orders", params, "orders")
|
|
67
|
+
|
|
68
|
+
def get_shipped_orders(
|
|
69
|
+
self, start_date: str = "2025-11-10", end_date: str = "3500-12-11"
|
|
70
|
+
) -> list[OrderData]:
|
|
71
|
+
"""Get orders with shipped status."""
|
|
72
|
+
params = Params(
|
|
73
|
+
filter={"current_state": "4", "date_add": f"[{start_date},{end_date}]"},
|
|
74
|
+
display=["id", "shipping_number"],
|
|
75
|
+
date=True,
|
|
76
|
+
)
|
|
77
|
+
return self._query("orders", params, "orders")
|
|
78
|
+
|
|
79
|
+
def get_total_wrapping(self, order_id: str) -> str | None:
|
|
80
|
+
"""Get total wrapping (donation) for an order."""
|
|
81
|
+
order = self.get_by_id(order_id)
|
|
82
|
+
return order.total_wrapping
|
|
83
|
+
|
|
84
|
+
def get_total_shipping(self, order_id: str) -> str | None:
|
|
85
|
+
"""Get total shipping cost for an order."""
|
|
86
|
+
order = self.get_by_id(order_id)
|
|
87
|
+
return order.total_shipping
|
|
88
|
+
|
|
89
|
+
def get_total_discounts(self, order_id: str) -> str | None:
|
|
90
|
+
"""Get total discounts for an order."""
|
|
91
|
+
order = self.get_by_id(order_id)
|
|
92
|
+
return order.total_discounts
|
|
93
|
+
|
|
94
|
+
def get_all_orders_since(
|
|
95
|
+
self, start_date: str = "2025-11-10", end_date: str = "3500-12-11"
|
|
96
|
+
) -> list[OrderData]:
|
|
97
|
+
"""Get all orders since a specific date."""
|
|
98
|
+
params = Params(
|
|
99
|
+
filter={"date_add": f"[{start_date},{end_date}]"},
|
|
100
|
+
display=["id", "reference", "date_add", "current_state", "total_paid"],
|
|
101
|
+
date=True,
|
|
102
|
+
)
|
|
103
|
+
return self._query("orders", params, "orders")
|
|
104
|
+
|
|
105
|
+
def get_orders_available_at_pickup_point(
|
|
106
|
+
self, start_date: str = "2025-11-10", end_date: str = "3500-12-11"
|
|
107
|
+
) -> list[OrderData]:
|
|
108
|
+
"""Get orders with shipped status."""
|
|
109
|
+
params = Params(
|
|
110
|
+
filter={"current_state": "41", "date_add": f"[{start_date},{end_date}]"},
|
|
111
|
+
display=["id", "shipping_number"],
|
|
112
|
+
date=True,
|
|
113
|
+
)
|
|
114
|
+
return self._query("orders", params, "orders")
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from prestashop_webservice.base_model import BaseModel
|
|
2
|
+
from prestashop_webservice.models import OrderCarrierData
|
|
3
|
+
from prestashop_webservice.params import Params
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OrderCarrier(BaseModel):
|
|
7
|
+
"""Complex queries for order_carriers endpoint."""
|
|
8
|
+
|
|
9
|
+
_data_class = OrderCarrierData
|
|
10
|
+
|
|
11
|
+
def get_by_order(self, order_id: str) -> list[OrderCarrierData]:
|
|
12
|
+
"""Get carriers for a specific order."""
|
|
13
|
+
params = Params(
|
|
14
|
+
filter={"id_order": order_id},
|
|
15
|
+
display=["id", "id_order", "tracking_number"],
|
|
16
|
+
)
|
|
17
|
+
return self._query("order_carriers", params, "order_carriers")
|
|
18
|
+
|
|
19
|
+
def get_by_tracking(self, tracking: str) -> list[OrderCarrierData]:
|
|
20
|
+
"""Find order carriers by tracking number."""
|
|
21
|
+
params = Params(
|
|
22
|
+
filter={"tracking_number": tracking},
|
|
23
|
+
display=["id", "id_order", "tracking_number"],
|
|
24
|
+
)
|
|
25
|
+
result = self._query("order_carriers", params, "order_carriers")
|
|
26
|
+
return result if result is not None else []
|
|
27
|
+
|
|
28
|
+
def get_latest_by_tracking(self, tracking: str) -> OrderCarrierData | None:
|
|
29
|
+
"""Get the most recent order carrier by tracking number."""
|
|
30
|
+
carriers = self.get_by_tracking(tracking)
|
|
31
|
+
if not carriers:
|
|
32
|
+
return None
|
|
33
|
+
return max(carriers, key=lambda r: r.id)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from prestashop_webservice.base_model import BaseModel
|
|
2
|
+
from prestashop_webservice.models import OrderDetailData
|
|
3
|
+
from prestashop_webservice.params import Params
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OrderDetail(BaseModel):
|
|
7
|
+
"""Complex queries for order_details endpoint."""
|
|
8
|
+
|
|
9
|
+
_data_class = OrderDetailData
|
|
10
|
+
|
|
11
|
+
def get_by_id(self, order_detail_id: str) -> OrderDetailData:
|
|
12
|
+
"""Get order detail by ID."""
|
|
13
|
+
return self._query(f"order_details/{order_detail_id}", None, "order_detail")
|
|
14
|
+
|
|
15
|
+
def get_by_order(self, order_id: str) -> list[OrderDetailData]:
|
|
16
|
+
"""Get details (products) for a specific order."""
|
|
17
|
+
params = Params(filter={"id_order": order_id}, display=["full"])
|
|
18
|
+
return self._query("order_details", params, "order_details")
|
|
19
|
+
|
|
20
|
+
def get_by_orders(self, order_ids: list[str]) -> list[OrderDetailData]:
|
|
21
|
+
"""Get details for multiple orders."""
|
|
22
|
+
if not order_ids:
|
|
23
|
+
return []
|
|
24
|
+
|
|
25
|
+
orders_filter_value = "|".join(order_ids)
|
|
26
|
+
|
|
27
|
+
params = Params(filter={"id_order": f"[{orders_filter_value}]"}, display=["full"])
|
|
28
|
+
return self._query("order_details", params, "order_details")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from prestashop_webservice.base_model import BaseModel
|
|
2
|
+
from prestashop_webservice.logger import logger
|
|
3
|
+
from prestashop_webservice.models import OrderHistoryData
|
|
4
|
+
from prestashop_webservice.params import Params
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OrderHistory(BaseModel):
|
|
8
|
+
"""Complex queries for order_histories endpoint."""
|
|
9
|
+
|
|
10
|
+
_data_class = OrderHistoryData
|
|
11
|
+
|
|
12
|
+
def get_by_order(self, order_id: str) -> list[OrderHistoryData]:
|
|
13
|
+
"""Get history for a specific order."""
|
|
14
|
+
params = Params(
|
|
15
|
+
filter={"id_order": order_id},
|
|
16
|
+
display=["id", "id_order", "id_order_state", "date_add"],
|
|
17
|
+
)
|
|
18
|
+
return self._query("order_histories", params, "order_histories")
|
|
19
|
+
|
|
20
|
+
def get_recent_changes(self, limit: int = 20) -> list[OrderHistoryData]:
|
|
21
|
+
"""Get recent order status changes."""
|
|
22
|
+
params = Params(
|
|
23
|
+
display=["id", "id_order", "id_order_state", "date_add"],
|
|
24
|
+
limit=limit,
|
|
25
|
+
)
|
|
26
|
+
return self._query("order_histories", params, "order_histories")
|
|
27
|
+
|
|
28
|
+
def get_by_status(self, status_id: str, limit: int = 100) -> list[OrderHistoryData]:
|
|
29
|
+
"""Get order histories by status."""
|
|
30
|
+
params = Params(
|
|
31
|
+
filter={"id_order_state": status_id},
|
|
32
|
+
display=["id", "id_order", "id_order_state"],
|
|
33
|
+
limit=limit,
|
|
34
|
+
)
|
|
35
|
+
return self._query("order_histories", params, "order_histories")
|
|
36
|
+
|
|
37
|
+
def create(self, order_id: str, order_state_id: str, date_add: str | None = None) -> bool:
|
|
38
|
+
xml_payload = f"""<?xml version="1.0" encoding="UTF-8"?>
|
|
39
|
+
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
40
|
+
<order_history>
|
|
41
|
+
<id_order>{order_id}</id_order>
|
|
42
|
+
<id_order_state>{order_state_id}</id_order_state>"""
|
|
43
|
+
if date_add:
|
|
44
|
+
xml_payload += f"\n <date_add>{date_add}</date_add>"
|
|
45
|
+
xml_payload += """
|
|
46
|
+
</order_history>
|
|
47
|
+
</prestashop>"""
|
|
48
|
+
|
|
49
|
+
logger.debug(f"Creating order history for order {order_id} with state {order_state_id}")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
self.client.post("order_histories", xml_payload)
|
|
53
|
+
logger.info(f"Order {order_id} status updated to {order_state_id}")
|
|
54
|
+
return True
|
|
55
|
+
except Exception as e:
|
|
56
|
+
logger.error(f"Failed to update order {order_id}: {e}")
|
|
57
|
+
return False
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from prestashop_webservice.base_model import BaseModel
|
|
2
|
+
from prestashop_webservice.models import OrderStateData
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OrderState(BaseModel):
|
|
6
|
+
"""Complex queries for order_states endpoint."""
|
|
7
|
+
|
|
8
|
+
_data_class = OrderStateData
|
|
9
|
+
|
|
10
|
+
def get_by_id(self, state_id: str) -> OrderStateData:
|
|
11
|
+
"""Get order state by ID."""
|
|
12
|
+
return self._query(f"order_states/{state_id}", None, "order_state")
|