ingestr 0.7.8__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ingestr/main.py +1 -0
- ingestr/src/adjust/_init_.py +31 -0
- ingestr/src/adjust/helpers.py +82 -0
- ingestr/src/appsflyer/_init_.py +24 -0
- ingestr/src/appsflyer/client.py +106 -0
- ingestr/src/factory.py +6 -0
- ingestr/src/shopify/__init__.py +1752 -54
- ingestr/src/shopify/helpers.py +73 -32
- ingestr/src/sources.py +89 -7
- ingestr/src/version.py +1 -1
- {ingestr-0.7.8.dist-info → ingestr-0.8.1.dist-info}/METADATA +10 -1
- {ingestr-0.7.8.dist-info → ingestr-0.8.1.dist-info}/RECORD +15 -11
- {ingestr-0.7.8.dist-info → ingestr-0.8.1.dist-info}/WHEEL +0 -0
- {ingestr-0.7.8.dist-info → ingestr-0.8.1.dist-info}/entry_points.txt +0 -0
- {ingestr-0.7.8.dist-info → ingestr-0.8.1.dist-info}/licenses/LICENSE.md +0 -0
ingestr/src/shopify/__init__.py
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
"""Fetches Shopify Orders and Products."""
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Iterable, Optional
|
|
4
4
|
|
|
5
5
|
import dlt
|
|
6
|
-
from dlt.common import jsonpath as jp
|
|
7
6
|
from dlt.common import pendulum
|
|
8
7
|
from dlt.common.time import ensure_pendulum_datetime
|
|
9
8
|
from dlt.common.typing import TAnyDateTime, TDataItem
|
|
10
9
|
from dlt.sources import DltResource
|
|
11
10
|
|
|
12
|
-
from .helpers import ShopifyApi,
|
|
11
|
+
from .helpers import ShopifyApi, ShopifyGraphQLApi, TOrderStatus
|
|
13
12
|
from .settings import (
|
|
14
13
|
DEFAULT_API_VERSION,
|
|
15
14
|
DEFAULT_ITEMS_PER_PAGE,
|
|
16
|
-
DEFAULT_PARTNER_API_VERSION,
|
|
17
15
|
FIRST_DAY_OF_MILLENNIUM,
|
|
18
16
|
)
|
|
19
17
|
|
|
@@ -63,8 +61,94 @@ def shopify_source(
|
|
|
63
61
|
created_at_min_obj = ensure_pendulum_datetime(created_at_min)
|
|
64
62
|
|
|
65
63
|
# define resources
|
|
66
|
-
@dlt.resource(
|
|
67
|
-
|
|
64
|
+
@dlt.resource(
|
|
65
|
+
primary_key="id",
|
|
66
|
+
write_disposition="merge",
|
|
67
|
+
columns={
|
|
68
|
+
"body_html": {
|
|
69
|
+
"data_type": "text",
|
|
70
|
+
"nullable": True,
|
|
71
|
+
"description": "A description of the product. Supports HTML formatting.",
|
|
72
|
+
},
|
|
73
|
+
"created_at": {
|
|
74
|
+
"data_type": "timestamp",
|
|
75
|
+
"nullable": False,
|
|
76
|
+
"description": "The date and time (ISO 8601 format) when the product was created.",
|
|
77
|
+
},
|
|
78
|
+
"handle": {
|
|
79
|
+
"data_type": "text",
|
|
80
|
+
"nullable": False,
|
|
81
|
+
"description": "A unique human-friendly string for the product. Automatically generated from the product's title. Used by the Liquid templating language to refer to objects.",
|
|
82
|
+
},
|
|
83
|
+
"id": {
|
|
84
|
+
"data_type": "bigint",
|
|
85
|
+
"nullable": False,
|
|
86
|
+
"primary_key": True,
|
|
87
|
+
"description": "An unsigned 64-bit integer that's used as a unique identifier for the product.",
|
|
88
|
+
},
|
|
89
|
+
"images": {
|
|
90
|
+
"data_type": "complex",
|
|
91
|
+
"nullable": True,
|
|
92
|
+
"description": "A list of product image objects, each one representing an image associated with the product.",
|
|
93
|
+
},
|
|
94
|
+
"options": {
|
|
95
|
+
"data_type": "complex",
|
|
96
|
+
"nullable": True,
|
|
97
|
+
"description": "The custom product properties. For example, Size, Color, and Material.",
|
|
98
|
+
},
|
|
99
|
+
"product_type": {
|
|
100
|
+
"data_type": "text",
|
|
101
|
+
"nullable": True,
|
|
102
|
+
"description": "A categorization for the product used for filtering and searching products.",
|
|
103
|
+
},
|
|
104
|
+
"published_at": {
|
|
105
|
+
"data_type": "timestamp",
|
|
106
|
+
"nullable": True,
|
|
107
|
+
"description": "The date and time (ISO 8601 format) when the product was published.",
|
|
108
|
+
},
|
|
109
|
+
"published_scope": {
|
|
110
|
+
"data_type": "text",
|
|
111
|
+
"nullable": True,
|
|
112
|
+
"description": "Whether the product is published to the Point of Sale channel.",
|
|
113
|
+
},
|
|
114
|
+
"status": {
|
|
115
|
+
"data_type": "text",
|
|
116
|
+
"nullable": False,
|
|
117
|
+
"description": "The status of the product.",
|
|
118
|
+
},
|
|
119
|
+
"tags": {
|
|
120
|
+
"data_type": "text",
|
|
121
|
+
"nullable": True,
|
|
122
|
+
"description": "A string of comma-separated tags used for filtering and search.",
|
|
123
|
+
},
|
|
124
|
+
"template_suffix": {
|
|
125
|
+
"data_type": "text",
|
|
126
|
+
"nullable": True,
|
|
127
|
+
"description": "The suffix of the Liquid template used for the product page.",
|
|
128
|
+
},
|
|
129
|
+
"title": {
|
|
130
|
+
"data_type": "text",
|
|
131
|
+
"nullable": False,
|
|
132
|
+
"description": "The name of the product.",
|
|
133
|
+
},
|
|
134
|
+
"updated_at": {
|
|
135
|
+
"data_type": "timestamp",
|
|
136
|
+
"nullable": True,
|
|
137
|
+
"description": "The date and time (ISO 8601 format) when the product was last modified.",
|
|
138
|
+
},
|
|
139
|
+
"variants": {
|
|
140
|
+
"data_type": "complex",
|
|
141
|
+
"nullable": True,
|
|
142
|
+
"description": "An array of product variants, each representing a different version of the product.",
|
|
143
|
+
},
|
|
144
|
+
"vendor": {
|
|
145
|
+
"data_type": "text",
|
|
146
|
+
"nullable": True,
|
|
147
|
+
"description": "The name of the product's vendor.",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
)
|
|
151
|
+
def products_legacy(
|
|
68
152
|
updated_at: dlt.sources.incremental[
|
|
69
153
|
pendulum.DateTime
|
|
70
154
|
] = dlt.sources.incremental(
|
|
@@ -95,7 +179,423 @@ def shopify_source(
|
|
|
95
179
|
params["updated_at_max"] = updated_at.end_value.isoformat()
|
|
96
180
|
yield from client.get_pages("products", params)
|
|
97
181
|
|
|
98
|
-
@dlt.resource(
|
|
182
|
+
@dlt.resource(
|
|
183
|
+
primary_key="id",
|
|
184
|
+
write_disposition="merge",
|
|
185
|
+
columns={
|
|
186
|
+
"app_id": {
|
|
187
|
+
"data_type": "bigint",
|
|
188
|
+
"nullable": True,
|
|
189
|
+
"description": "The ID of the app that created the order.",
|
|
190
|
+
},
|
|
191
|
+
"billing_address": {
|
|
192
|
+
"data_type": "complex",
|
|
193
|
+
"nullable": True,
|
|
194
|
+
"description": "The mailing address associated with the payment method.",
|
|
195
|
+
},
|
|
196
|
+
"browser_ip": {
|
|
197
|
+
"data_type": "text",
|
|
198
|
+
"nullable": True,
|
|
199
|
+
"description": "The IP address of the browser used by the customer when they placed the order.",
|
|
200
|
+
},
|
|
201
|
+
"buyer_accepts_marketing": {
|
|
202
|
+
"data_type": "bool",
|
|
203
|
+
"nullable": True,
|
|
204
|
+
"description": "Whether the customer consented to receive email updates from the shop.",
|
|
205
|
+
},
|
|
206
|
+
"cancel_reason": {
|
|
207
|
+
"data_type": "text",
|
|
208
|
+
"nullable": True,
|
|
209
|
+
"description": "The reason why the order was canceled.",
|
|
210
|
+
},
|
|
211
|
+
"cancelled_at": {
|
|
212
|
+
"data_type": "timestamp",
|
|
213
|
+
"nullable": True,
|
|
214
|
+
"description": "The date and time when the order was canceled.",
|
|
215
|
+
},
|
|
216
|
+
"cart_token": {
|
|
217
|
+
"data_type": "text",
|
|
218
|
+
"nullable": True,
|
|
219
|
+
"description": "A unique value referencing the cart associated with the order.",
|
|
220
|
+
},
|
|
221
|
+
"checkout_token": {
|
|
222
|
+
"data_type": "text",
|
|
223
|
+
"nullable": True,
|
|
224
|
+
"description": "A unique value referencing the checkout associated with the order.",
|
|
225
|
+
},
|
|
226
|
+
"client_details": {
|
|
227
|
+
"data_type": "complex",
|
|
228
|
+
"nullable": True,
|
|
229
|
+
"description": "Information about the browser the customer used when placing the order.",
|
|
230
|
+
},
|
|
231
|
+
"closed_at": {
|
|
232
|
+
"data_type": "timestamp",
|
|
233
|
+
"nullable": True,
|
|
234
|
+
"description": "The date and time when the order was closed.",
|
|
235
|
+
},
|
|
236
|
+
"company": {
|
|
237
|
+
"data_type": "complex",
|
|
238
|
+
"nullable": True,
|
|
239
|
+
"description": "Information about the purchasing company for the order.",
|
|
240
|
+
},
|
|
241
|
+
"confirmation_number": {
|
|
242
|
+
"data_type": "text",
|
|
243
|
+
"nullable": True,
|
|
244
|
+
"description": "A randomly generated identifier for the order.",
|
|
245
|
+
},
|
|
246
|
+
"confirmed": {
|
|
247
|
+
"data_type": "bool",
|
|
248
|
+
"nullable": True,
|
|
249
|
+
"description": "Whether inventory has been reserved for the order.",
|
|
250
|
+
},
|
|
251
|
+
"created_at": {
|
|
252
|
+
"data_type": "timestamp",
|
|
253
|
+
"nullable": False,
|
|
254
|
+
"description": "The autogenerated date and time when the order was created.",
|
|
255
|
+
},
|
|
256
|
+
"currency": {
|
|
257
|
+
"data_type": "text",
|
|
258
|
+
"nullable": False,
|
|
259
|
+
"description": "The three-letter code (ISO 4217 format) for the shop currency.",
|
|
260
|
+
},
|
|
261
|
+
"current_total_additional_fees_set": {
|
|
262
|
+
"data_type": "complex",
|
|
263
|
+
"nullable": True,
|
|
264
|
+
"description": "The current total additional fees on the order in shop and presentment currencies.",
|
|
265
|
+
},
|
|
266
|
+
"current_total_discounts": {
|
|
267
|
+
"data_type": "decimal",
|
|
268
|
+
"nullable": True,
|
|
269
|
+
"description": "The current total discounts on the order in the shop currency.",
|
|
270
|
+
},
|
|
271
|
+
"current_total_discounts_set": {
|
|
272
|
+
"data_type": "complex",
|
|
273
|
+
"nullable": True,
|
|
274
|
+
"description": "The current total discounts on the order in shop and presentment currencies.",
|
|
275
|
+
},
|
|
276
|
+
"current_total_duties_set": {
|
|
277
|
+
"data_type": "complex",
|
|
278
|
+
"nullable": True,
|
|
279
|
+
"description": "The current total duties charged on the order in shop and presentment currencies.",
|
|
280
|
+
},
|
|
281
|
+
"current_total_price": {
|
|
282
|
+
"data_type": "decimal",
|
|
283
|
+
"nullable": True,
|
|
284
|
+
"description": "The current total price of the order in the shop currency.",
|
|
285
|
+
},
|
|
286
|
+
"current_total_price_set": {
|
|
287
|
+
"data_type": "complex",
|
|
288
|
+
"nullable": True,
|
|
289
|
+
"description": "The current total price of the order in shop and presentment currencies.",
|
|
290
|
+
},
|
|
291
|
+
"current_subtotal_price": {
|
|
292
|
+
"data_type": "decimal",
|
|
293
|
+
"nullable": True,
|
|
294
|
+
"description": "The sum of prices for all line items after discounts and returns in the shop currency.",
|
|
295
|
+
},
|
|
296
|
+
"current_subtotal_price_set": {
|
|
297
|
+
"data_type": "complex",
|
|
298
|
+
"nullable": True,
|
|
299
|
+
"description": "The sum of the prices for all line items after discounts and returns in shop and presentment currencies.",
|
|
300
|
+
},
|
|
301
|
+
"current_total_tax": {
|
|
302
|
+
"data_type": "decimal",
|
|
303
|
+
"nullable": True,
|
|
304
|
+
"description": "The sum of the prices for all tax lines applied to the order in the shop currency.",
|
|
305
|
+
},
|
|
306
|
+
"current_total_tax_set": {
|
|
307
|
+
"data_type": "complex",
|
|
308
|
+
"nullable": True,
|
|
309
|
+
"description": "The sum of the prices for all tax lines applied to the order in shop and presentment currencies.",
|
|
310
|
+
},
|
|
311
|
+
"customer": {
|
|
312
|
+
"data_type": "complex",
|
|
313
|
+
"nullable": True,
|
|
314
|
+
"description": "Information about the customer.",
|
|
315
|
+
},
|
|
316
|
+
"customer_locale": {
|
|
317
|
+
"data_type": "text",
|
|
318
|
+
"nullable": True,
|
|
319
|
+
"description": "The two or three-letter language code, optionally followed by a region modifier.",
|
|
320
|
+
},
|
|
321
|
+
"discount_applications": {
|
|
322
|
+
"data_type": "complex",
|
|
323
|
+
"nullable": True,
|
|
324
|
+
"description": "An ordered list of stacked discount applications.",
|
|
325
|
+
},
|
|
326
|
+
"discount_codes": {
|
|
327
|
+
"data_type": "complex",
|
|
328
|
+
"nullable": True,
|
|
329
|
+
"description": "A list of discounts applied to the order.",
|
|
330
|
+
},
|
|
331
|
+
"email": {
|
|
332
|
+
"data_type": "text",
|
|
333
|
+
"nullable": True,
|
|
334
|
+
"description": "The customer's email address.",
|
|
335
|
+
},
|
|
336
|
+
"estimated_taxes": {
|
|
337
|
+
"data_type": "bool",
|
|
338
|
+
"nullable": True,
|
|
339
|
+
"description": "Whether taxes on the order are estimated.",
|
|
340
|
+
},
|
|
341
|
+
"financial_status": {
|
|
342
|
+
"data_type": "text",
|
|
343
|
+
"nullable": True,
|
|
344
|
+
"description": "The status of payments associated with the order.",
|
|
345
|
+
},
|
|
346
|
+
"fulfillments": {
|
|
347
|
+
"data_type": "complex",
|
|
348
|
+
"nullable": True,
|
|
349
|
+
"description": "An array of fulfillments associated with the order.",
|
|
350
|
+
},
|
|
351
|
+
"fulfillment_status": {
|
|
352
|
+
"data_type": "text",
|
|
353
|
+
"nullable": True,
|
|
354
|
+
"description": "The order's status in terms of fulfilled line items.",
|
|
355
|
+
},
|
|
356
|
+
"gateway": {
|
|
357
|
+
"data_type": "text",
|
|
358
|
+
"nullable": True,
|
|
359
|
+
"description": "The payment gateway used.",
|
|
360
|
+
},
|
|
361
|
+
"id": {
|
|
362
|
+
"data_type": "bigint",
|
|
363
|
+
"nullable": False,
|
|
364
|
+
"primary_key": True,
|
|
365
|
+
"description": "The ID of the order, used for API purposes.",
|
|
366
|
+
},
|
|
367
|
+
"landing_site": {
|
|
368
|
+
"data_type": "text",
|
|
369
|
+
"nullable": True,
|
|
370
|
+
"description": "The URL for the page where the buyer landed when they entered the shop.",
|
|
371
|
+
},
|
|
372
|
+
"line_items": {
|
|
373
|
+
"data_type": "complex",
|
|
374
|
+
"nullable": True,
|
|
375
|
+
"description": "A list of line item objects containing information about an item in the order.",
|
|
376
|
+
},
|
|
377
|
+
"location_id": {
|
|
378
|
+
"data_type": "bigint",
|
|
379
|
+
"nullable": True,
|
|
380
|
+
"description": "The ID of one of the locations assigned to fulfill the order.",
|
|
381
|
+
},
|
|
382
|
+
"merchant_of_record_app_id": {
|
|
383
|
+
"data_type": "bigint",
|
|
384
|
+
"nullable": True,
|
|
385
|
+
"description": "The application acting as Merchant of Record for the order.",
|
|
386
|
+
},
|
|
387
|
+
"name": {
|
|
388
|
+
"data_type": "text",
|
|
389
|
+
"nullable": True,
|
|
390
|
+
"description": "The order name, generated by combining the order_number with the order prefix and suffix.",
|
|
391
|
+
},
|
|
392
|
+
"note": {
|
|
393
|
+
"data_type": "text",
|
|
394
|
+
"nullable": True,
|
|
395
|
+
"description": "An optional note that a shop owner can attach to the order.",
|
|
396
|
+
},
|
|
397
|
+
"note_attributes": {
|
|
398
|
+
"data_type": "complex",
|
|
399
|
+
"nullable": True,
|
|
400
|
+
"description": "Extra information added to the order as key-value pairs.",
|
|
401
|
+
},
|
|
402
|
+
"number": {
|
|
403
|
+
"data_type": "bigint",
|
|
404
|
+
"nullable": True,
|
|
405
|
+
"description": "The order's position in the shop's count of orders.",
|
|
406
|
+
},
|
|
407
|
+
"order_number": {
|
|
408
|
+
"data_type": "bigint",
|
|
409
|
+
"nullable": True,
|
|
410
|
+
"description": "The order's position in the shop's count of orders, starting at 1001.",
|
|
411
|
+
},
|
|
412
|
+
"original_total_additional_fees_set": {
|
|
413
|
+
"data_type": "complex",
|
|
414
|
+
"nullable": True,
|
|
415
|
+
"description": "The original total additional fees on the order in shop and presentment currencies.",
|
|
416
|
+
},
|
|
417
|
+
"original_total_duties_set": {
|
|
418
|
+
"data_type": "complex",
|
|
419
|
+
"nullable": True,
|
|
420
|
+
"description": "The original total duties charged on the order in shop and presentment currencies.",
|
|
421
|
+
},
|
|
422
|
+
"payment_terms": {
|
|
423
|
+
"data_type": "complex",
|
|
424
|
+
"nullable": True,
|
|
425
|
+
"description": "The terms and conditions under which a payment should be processed.",
|
|
426
|
+
},
|
|
427
|
+
"payment_gateway_names": {
|
|
428
|
+
"data_type": "complex",
|
|
429
|
+
"nullable": True,
|
|
430
|
+
"description": "The list of payment gateways used for the order.",
|
|
431
|
+
},
|
|
432
|
+
"phone": {
|
|
433
|
+
"data_type": "text",
|
|
434
|
+
"nullable": True,
|
|
435
|
+
"description": "The customer's phone number for receiving SMS notifications.",
|
|
436
|
+
},
|
|
437
|
+
"po_number": {
|
|
438
|
+
"data_type": "text",
|
|
439
|
+
"nullable": True,
|
|
440
|
+
"description": "The purchase order number associated with the order.",
|
|
441
|
+
},
|
|
442
|
+
"presentment_currency": {
|
|
443
|
+
"data_type": "text",
|
|
444
|
+
"nullable": True,
|
|
445
|
+
"description": "The presentment currency used to display prices to the customer.",
|
|
446
|
+
},
|
|
447
|
+
"processed_at": {
|
|
448
|
+
"data_type": "timestamp",
|
|
449
|
+
"nullable": True,
|
|
450
|
+
"description": "The date and time when an order was processed.",
|
|
451
|
+
},
|
|
452
|
+
"referring_site": {
|
|
453
|
+
"data_type": "text",
|
|
454
|
+
"nullable": True,
|
|
455
|
+
"description": "The website where the customer clicked a link to the shop.",
|
|
456
|
+
},
|
|
457
|
+
"refunds": {
|
|
458
|
+
"data_type": "complex",
|
|
459
|
+
"nullable": True,
|
|
460
|
+
"description": "A list of refunds applied to the order.",
|
|
461
|
+
},
|
|
462
|
+
"shipping_address": {
|
|
463
|
+
"data_type": "complex",
|
|
464
|
+
"nullable": True,
|
|
465
|
+
"description": "The mailing address where the order will be shipped.",
|
|
466
|
+
},
|
|
467
|
+
"shipping_lines": {
|
|
468
|
+
"data_type": "complex",
|
|
469
|
+
"nullable": True,
|
|
470
|
+
"description": "An array detailing the shipping methods used.",
|
|
471
|
+
},
|
|
472
|
+
"source_name": {
|
|
473
|
+
"data_type": "text",
|
|
474
|
+
"nullable": True,
|
|
475
|
+
"description": "The source of the checkout.",
|
|
476
|
+
},
|
|
477
|
+
"source_identifier": {
|
|
478
|
+
"data_type": "text",
|
|
479
|
+
"nullable": True,
|
|
480
|
+
"description": "The ID of the order placed on the originating platform.",
|
|
481
|
+
},
|
|
482
|
+
"source_url": {
|
|
483
|
+
"data_type": "text",
|
|
484
|
+
"nullable": True,
|
|
485
|
+
"description": "A valid URL to the original order on the originating surface.",
|
|
486
|
+
},
|
|
487
|
+
"subtotal_price": {
|
|
488
|
+
"data_type": "decimal",
|
|
489
|
+
"nullable": True,
|
|
490
|
+
"description": "The price of the order in the shop currency after discounts but before shipping, duties, taxes, and tips.",
|
|
491
|
+
},
|
|
492
|
+
"subtotal_price_set": {
|
|
493
|
+
"data_type": "complex",
|
|
494
|
+
"nullable": True,
|
|
495
|
+
"description": "The subtotal of the order in shop and presentment currencies after discounts but before shipping, duties, taxes, and tips.",
|
|
496
|
+
},
|
|
497
|
+
"tags": {
|
|
498
|
+
"data_type": "text",
|
|
499
|
+
"nullable": True,
|
|
500
|
+
"description": "Tags attached to the order, formatted as a string of comma-separated values.",
|
|
501
|
+
},
|
|
502
|
+
"tax_lines": {
|
|
503
|
+
"data_type": "complex",
|
|
504
|
+
"nullable": True,
|
|
505
|
+
"description": "An array of tax line objects detailing taxes applied to the order.",
|
|
506
|
+
},
|
|
507
|
+
"taxes_included": {
|
|
508
|
+
"data_type": "bool",
|
|
509
|
+
"nullable": True,
|
|
510
|
+
"description": "Whether taxes are included in the order subtotal.",
|
|
511
|
+
},
|
|
512
|
+
"test": {
|
|
513
|
+
"data_type": "bool",
|
|
514
|
+
"nullable": True,
|
|
515
|
+
"description": "Whether this is a test order.",
|
|
516
|
+
},
|
|
517
|
+
"token": {
|
|
518
|
+
"data_type": "text",
|
|
519
|
+
"nullable": True,
|
|
520
|
+
"description": "A unique value referencing the order.",
|
|
521
|
+
},
|
|
522
|
+
"total_discounts": {
|
|
523
|
+
"data_type": "decimal",
|
|
524
|
+
"nullable": True,
|
|
525
|
+
"description": "The total discounts applied to the price of the order in the shop currency.",
|
|
526
|
+
},
|
|
527
|
+
"total_discounts_set": {
|
|
528
|
+
"data_type": "complex",
|
|
529
|
+
"nullable": True,
|
|
530
|
+
"description": "The total discounts applied to the price of the order in shop and presentment currencies.",
|
|
531
|
+
},
|
|
532
|
+
"total_line_items_price": {
|
|
533
|
+
"data_type": "decimal",
|
|
534
|
+
"nullable": True,
|
|
535
|
+
"description": "The sum of all line item prices in the shop currency.",
|
|
536
|
+
},
|
|
537
|
+
"total_line_items_price_set": {
|
|
538
|
+
"data_type": "complex",
|
|
539
|
+
"nullable": True,
|
|
540
|
+
"description": "The total of all line item prices in shop and presentment currencies.",
|
|
541
|
+
},
|
|
542
|
+
"total_outstanding": {
|
|
543
|
+
"data_type": "decimal",
|
|
544
|
+
"nullable": True,
|
|
545
|
+
"description": "The total outstanding amount of the order in the shop currency.",
|
|
546
|
+
},
|
|
547
|
+
"total_price": {
|
|
548
|
+
"data_type": "decimal",
|
|
549
|
+
"nullable": True,
|
|
550
|
+
"description": "The sum of all line item prices, discounts, shipping, taxes, and tips in the shop currency.",
|
|
551
|
+
},
|
|
552
|
+
"total_price_set": {
|
|
553
|
+
"data_type": "complex",
|
|
554
|
+
"nullable": True,
|
|
555
|
+
"description": "The total price of the order in shop and presentment currencies.",
|
|
556
|
+
},
|
|
557
|
+
"total_shipping_price_set": {
|
|
558
|
+
"data_type": "complex",
|
|
559
|
+
"nullable": True,
|
|
560
|
+
"description": "The total shipping price of the order in shop and presentment currencies.",
|
|
561
|
+
},
|
|
562
|
+
"total_tax": {
|
|
563
|
+
"data_type": "decimal",
|
|
564
|
+
"nullable": True,
|
|
565
|
+
"description": "The sum of the prices for all tax lines applied to the order in the shop currency.",
|
|
566
|
+
},
|
|
567
|
+
"total_tax_set": {
|
|
568
|
+
"data_type": "complex",
|
|
569
|
+
"nullable": True,
|
|
570
|
+
"description": "The sum of the prices for all tax lines applied to the order in shop and presentment currencies.",
|
|
571
|
+
},
|
|
572
|
+
"total_tip_received": {
|
|
573
|
+
"data_type": "decimal",
|
|
574
|
+
"nullable": True,
|
|
575
|
+
"description": "The sum of all the tips in the order in the shop currency.",
|
|
576
|
+
},
|
|
577
|
+
"total_weight": {
|
|
578
|
+
"data_type": "decimal",
|
|
579
|
+
"nullable": True,
|
|
580
|
+
"description": "The sum of all line item weights in grams.",
|
|
581
|
+
},
|
|
582
|
+
"updated_at": {
|
|
583
|
+
"data_type": "timestamp",
|
|
584
|
+
"nullable": True,
|
|
585
|
+
"description": "The date and time when the order was last modified.",
|
|
586
|
+
},
|
|
587
|
+
"user_id": {
|
|
588
|
+
"data_type": "bigint",
|
|
589
|
+
"nullable": True,
|
|
590
|
+
"description": "The ID of the user logged into Shopify POS who processed the order.",
|
|
591
|
+
},
|
|
592
|
+
"order_status_url": {
|
|
593
|
+
"data_type": "text",
|
|
594
|
+
"nullable": True,
|
|
595
|
+
"description": "The URL pointing to the order status web page, if applicable.",
|
|
596
|
+
},
|
|
597
|
+
},
|
|
598
|
+
)
|
|
99
599
|
def orders(
|
|
100
600
|
updated_at: dlt.sources.incremental[
|
|
101
601
|
pendulum.DateTime
|
|
@@ -161,67 +661,1265 @@ def shopify_source(
|
|
|
161
661
|
params["updated_at_max"] = updated_at.end_value.isoformat()
|
|
162
662
|
yield from client.get_pages("customers", params)
|
|
163
663
|
|
|
164
|
-
|
|
664
|
+
@dlt.resource(primary_key="id", write_disposition="append")
|
|
665
|
+
def events(
|
|
666
|
+
created_at: dlt.sources.incremental[
|
|
667
|
+
pendulum.DateTime
|
|
668
|
+
] = dlt.sources.incremental(
|
|
669
|
+
"created_at",
|
|
670
|
+
initial_value=start_date_obj,
|
|
671
|
+
end_value=end_date_obj,
|
|
672
|
+
),
|
|
673
|
+
items_per_page: int = items_per_page,
|
|
674
|
+
) -> Iterable[TDataItem]:
|
|
675
|
+
params = dict(
|
|
676
|
+
created_at_min=created_at.last_value.isoformat(),
|
|
677
|
+
limit=items_per_page,
|
|
678
|
+
order="created_at asc",
|
|
679
|
+
)
|
|
680
|
+
yield from client.get_pages("events", params)
|
|
165
681
|
|
|
682
|
+
@dlt.resource(primary_key="id", write_disposition="merge")
|
|
683
|
+
def price_rules(
|
|
684
|
+
updated_at: dlt.sources.incremental[
|
|
685
|
+
pendulum.DateTime
|
|
686
|
+
] = dlt.sources.incremental(
|
|
687
|
+
"updated_at",
|
|
688
|
+
initial_value=start_date_obj,
|
|
689
|
+
end_value=end_date_obj,
|
|
690
|
+
),
|
|
691
|
+
items_per_page: int = items_per_page,
|
|
692
|
+
) -> Iterable[TDataItem]:
|
|
693
|
+
params = dict(
|
|
694
|
+
updated_at_min=updated_at.last_value.isoformat(),
|
|
695
|
+
limit=items_per_page,
|
|
696
|
+
order="updated_at asc",
|
|
697
|
+
)
|
|
698
|
+
yield from client.get_pages("price_rules", params)
|
|
166
699
|
|
|
167
|
-
@dlt.resource
|
|
168
|
-
def
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
|
|
700
|
+
@dlt.resource(primary_key="id", write_disposition="merge")
|
|
701
|
+
def transactions(
|
|
702
|
+
since_id: dlt.sources.incremental[int] = dlt.sources.incremental(
|
|
703
|
+
"id",
|
|
704
|
+
initial_value=None,
|
|
705
|
+
),
|
|
706
|
+
items_per_page: int = items_per_page,
|
|
707
|
+
) -> Iterable[TDataItem]:
|
|
708
|
+
params = dict(
|
|
709
|
+
limit=items_per_page,
|
|
710
|
+
)
|
|
711
|
+
if since_id.start_value is not None:
|
|
712
|
+
params["since_id"] = since_id.start_value
|
|
713
|
+
yield from client.get_pages("shopify_payments/balance/transactions", params)
|
|
714
|
+
|
|
715
|
+
@dlt.resource(
|
|
716
|
+
primary_key="currency",
|
|
717
|
+
write_disposition={"disposition": "merge", "strategy": "scd2"},
|
|
718
|
+
)
|
|
719
|
+
def balance() -> Iterable[TDataItem]:
|
|
720
|
+
yield from client.get_pages("shopify_payments/balance", {})
|
|
180
721
|
|
|
181
|
-
|
|
182
|
-
|
|
722
|
+
@dlt.resource(primary_key="id", write_disposition="merge")
|
|
723
|
+
def inventory_items(
|
|
724
|
+
updated_at: dlt.sources.incremental[
|
|
725
|
+
pendulum.DateTime
|
|
726
|
+
] = dlt.sources.incremental(
|
|
727
|
+
"updatedAt",
|
|
728
|
+
initial_value=start_date_obj,
|
|
729
|
+
end_value=end_date_obj,
|
|
730
|
+
allow_external_schedulers=True,
|
|
731
|
+
),
|
|
732
|
+
items_per_page: int = items_per_page,
|
|
733
|
+
) -> Iterable[TDataItem]:
|
|
734
|
+
client = ShopifyGraphQLApi(
|
|
735
|
+
base_url=shop_url,
|
|
736
|
+
access_token=private_app_password,
|
|
737
|
+
api_version="2024-07",
|
|
738
|
+
)
|
|
183
739
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
740
|
+
query = """
|
|
741
|
+
query inventoryItems($after: String, $query: String, $first: Int) {
|
|
742
|
+
inventoryItems(after: $after, first: $first, query: $query) {
|
|
187
743
|
edges {
|
|
188
|
-
|
|
189
|
-
|
|
744
|
+
node {
|
|
745
|
+
id
|
|
746
|
+
countryCodeOfOrigin
|
|
747
|
+
createdAt
|
|
748
|
+
duplicateSkuCount
|
|
749
|
+
harmonizedSystemCode
|
|
750
|
+
inventoryHistoryUrl
|
|
751
|
+
legacyResourceId
|
|
752
|
+
measurement {
|
|
753
|
+
id
|
|
754
|
+
weight {
|
|
755
|
+
unit
|
|
756
|
+
value
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
provinceCodeOfOrigin
|
|
761
|
+
requiresShipping
|
|
762
|
+
sku
|
|
763
|
+
tracked
|
|
764
|
+
trackedEditable {
|
|
765
|
+
locked
|
|
766
|
+
reason
|
|
767
|
+
}
|
|
768
|
+
unitCost {
|
|
769
|
+
amount
|
|
770
|
+
currencyCode
|
|
771
|
+
}
|
|
772
|
+
updatedAt
|
|
773
|
+
variant {
|
|
774
|
+
id
|
|
775
|
+
availableForSale
|
|
776
|
+
barcode
|
|
777
|
+
|
|
778
|
+
compareAtPrice
|
|
779
|
+
createdAt
|
|
780
|
+
inventoryPolicy
|
|
781
|
+
inventoryQuantity
|
|
782
|
+
legacyResourceId
|
|
783
|
+
|
|
784
|
+
position
|
|
785
|
+
price
|
|
786
|
+
product {
|
|
190
787
|
id
|
|
191
788
|
}
|
|
789
|
+
requiresComponents
|
|
790
|
+
|
|
791
|
+
selectedOptions {
|
|
792
|
+
name
|
|
793
|
+
value
|
|
794
|
+
}
|
|
795
|
+
sellableOnlineQuantity
|
|
796
|
+
|
|
797
|
+
sellingPlanGroupsCount {
|
|
798
|
+
count
|
|
799
|
+
precision
|
|
800
|
+
}
|
|
801
|
+
sku
|
|
802
|
+
|
|
803
|
+
taxCode
|
|
804
|
+
taxable
|
|
805
|
+
title
|
|
806
|
+
updatedAt
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
pageInfo {
|
|
811
|
+
endCursor
|
|
192
812
|
}
|
|
193
813
|
}
|
|
194
|
-
}
|
|
814
|
+
}"""
|
|
195
815
|
|
|
196
|
-
|
|
816
|
+
yield from client.get_graphql_pages(
|
|
197
817
|
query,
|
|
198
|
-
data_items_path="data.
|
|
199
|
-
pagination_cursor_path="data.
|
|
818
|
+
data_items_path="data.inventoryItems.edges[*].node",
|
|
819
|
+
pagination_cursor_path="data.inventoryItems.pageInfo.endCursor",
|
|
200
820
|
pagination_variable_name="after",
|
|
821
|
+
variables={
|
|
822
|
+
"query": f"updated_at:>'{updated_at.last_value.isoformat()}'",
|
|
823
|
+
"first": items_per_page,
|
|
824
|
+
},
|
|
201
825
|
)
|
|
202
826
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
827
|
+
@dlt.resource(primary_key="id", write_disposition="merge")
|
|
828
|
+
def discounts(items_per_page: int = items_per_page) -> Iterable[TDataItem]:
|
|
829
|
+
client = ShopifyGraphQLApi(
|
|
830
|
+
base_url=shop_url,
|
|
831
|
+
access_token=private_app_password,
|
|
832
|
+
api_version="2024-07",
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
query = """
|
|
836
|
+
query discountNodes($after: String, $query: String, $first: Int) {
|
|
837
|
+
discountNodes(after: $after, first: $first, query: $query) {
|
|
838
|
+
nodes {
|
|
839
|
+
id
|
|
840
|
+
discount {
|
|
841
|
+
__typename
|
|
842
|
+
... on DiscountCodeApp {
|
|
843
|
+
appDiscountType {
|
|
844
|
+
app {
|
|
845
|
+
id
|
|
846
|
+
}
|
|
847
|
+
functionId
|
|
848
|
+
targetType
|
|
849
|
+
}
|
|
850
|
+
appliesOncePerCustomer
|
|
851
|
+
asyncUsageCount
|
|
852
|
+
combinesWith {
|
|
853
|
+
orderDiscounts
|
|
854
|
+
productDiscounts
|
|
855
|
+
shippingDiscounts
|
|
856
|
+
}
|
|
857
|
+
codesCount {
|
|
858
|
+
count
|
|
859
|
+
precision
|
|
860
|
+
}
|
|
861
|
+
createdAt
|
|
862
|
+
customerSelection {
|
|
863
|
+
__typename
|
|
864
|
+
... on DiscountCustomerAll {
|
|
865
|
+
allCustomers
|
|
866
|
+
}
|
|
867
|
+
... on DiscountCustomerSegments {
|
|
868
|
+
segments {
|
|
869
|
+
creationDate
|
|
870
|
+
id
|
|
871
|
+
lastEditDate
|
|
872
|
+
name
|
|
873
|
+
query
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
... on DiscountCustomers {
|
|
877
|
+
customers {
|
|
878
|
+
id
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
discountClass
|
|
883
|
+
discountId
|
|
884
|
+
endsAt
|
|
885
|
+
errorHistory {
|
|
886
|
+
errorsFirstOccurredAt
|
|
887
|
+
firstOccurredAt
|
|
888
|
+
hasBeenSharedSinceLastError
|
|
889
|
+
hasSharedRecentErrors
|
|
890
|
+
}
|
|
891
|
+
hasTimelineComment
|
|
892
|
+
recurringCycleLimit
|
|
893
|
+
shareableUrls {
|
|
894
|
+
targetItemImage {
|
|
895
|
+
id
|
|
896
|
+
url
|
|
897
|
+
}
|
|
898
|
+
targetType
|
|
899
|
+
title
|
|
900
|
+
url
|
|
901
|
+
}
|
|
902
|
+
startsAt
|
|
903
|
+
status
|
|
904
|
+
title
|
|
905
|
+
totalSales {
|
|
906
|
+
amount
|
|
907
|
+
currencyCode
|
|
908
|
+
}
|
|
909
|
+
updatedAt
|
|
910
|
+
usageLimit
|
|
911
|
+
}
|
|
912
|
+
... on DiscountCodeBasic {
|
|
913
|
+
appliesOncePerCustomer
|
|
914
|
+
asyncUsageCount
|
|
915
|
+
codes: codes(first: 250) {
|
|
916
|
+
nodes {
|
|
917
|
+
id
|
|
918
|
+
code
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
codesCount {
|
|
922
|
+
count
|
|
923
|
+
precision
|
|
924
|
+
}
|
|
925
|
+
combinesWith {
|
|
926
|
+
orderDiscounts
|
|
927
|
+
productDiscounts
|
|
928
|
+
shippingDiscounts
|
|
929
|
+
}
|
|
930
|
+
createdAt
|
|
931
|
+
customerGets {
|
|
932
|
+
appliesOnOneTimePurchase
|
|
933
|
+
appliesOnSubscription
|
|
934
|
+
items {
|
|
935
|
+
__typename
|
|
936
|
+
... on AllDiscountItems {
|
|
937
|
+
allItems
|
|
938
|
+
}
|
|
939
|
+
... on DiscountCollections {
|
|
940
|
+
collectionsFirst250: collections(first: 250) {
|
|
941
|
+
nodes {
|
|
942
|
+
id
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
... on DiscountProducts {
|
|
947
|
+
productsFirst250: products(first: 250) {
|
|
948
|
+
nodes {
|
|
949
|
+
id
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
953
|
+
nodes {
|
|
954
|
+
id
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
value {
|
|
960
|
+
__typename
|
|
961
|
+
... on DiscountAmount {
|
|
962
|
+
amount {
|
|
963
|
+
amount
|
|
964
|
+
currencyCode
|
|
965
|
+
}
|
|
966
|
+
appliesOnEachItem
|
|
967
|
+
}
|
|
968
|
+
... on DiscountOnQuantity {
|
|
969
|
+
effect {
|
|
970
|
+
... on DiscountAmount {
|
|
971
|
+
amount {
|
|
972
|
+
amount
|
|
973
|
+
currencyCode
|
|
974
|
+
}
|
|
975
|
+
appliesOnEachItem
|
|
976
|
+
}
|
|
977
|
+
... on DiscountPercentage {
|
|
978
|
+
percentage
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
quantity {
|
|
982
|
+
quantity
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
... on DiscountPercentage {
|
|
986
|
+
percentage
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
customerSelection {
|
|
991
|
+
__typename
|
|
992
|
+
... on DiscountCustomerAll {
|
|
993
|
+
allCustomers
|
|
994
|
+
}
|
|
995
|
+
... on DiscountCustomerSegments {
|
|
996
|
+
segments {
|
|
997
|
+
creationDate
|
|
998
|
+
id
|
|
999
|
+
lastEditDate
|
|
1000
|
+
name
|
|
1001
|
+
query
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
... on DiscountCustomers {
|
|
1005
|
+
customers {
|
|
1006
|
+
id
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
discountClass
|
|
1011
|
+
endsAt
|
|
1012
|
+
hasTimelineComment
|
|
1013
|
+
minimumRequirement {
|
|
1014
|
+
__typename
|
|
1015
|
+
... on DiscountMinimumQuantity {
|
|
1016
|
+
greaterThanOrEqualToQuantity
|
|
1017
|
+
}
|
|
1018
|
+
... on DiscountMinimumSubtotal {
|
|
1019
|
+
greaterThanOrEqualToSubtotal {
|
|
1020
|
+
amount
|
|
1021
|
+
currencyCode
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
recurringCycleLimit
|
|
1026
|
+
shareableUrls {
|
|
1027
|
+
url
|
|
1028
|
+
title
|
|
1029
|
+
}
|
|
1030
|
+
shortSummary
|
|
1031
|
+
startsAt
|
|
1032
|
+
status
|
|
1033
|
+
summary
|
|
1034
|
+
title
|
|
1035
|
+
totalSales {
|
|
1036
|
+
amount
|
|
1037
|
+
currencyCode
|
|
1038
|
+
}
|
|
1039
|
+
updatedAt
|
|
1040
|
+
usageLimit
|
|
1041
|
+
}
|
|
1042
|
+
... on DiscountCodeBxgy {
|
|
1043
|
+
appliesOncePerCustomer
|
|
1044
|
+
asyncUsageCount
|
|
1045
|
+
codesFirst50: codes(first: 50) {
|
|
1046
|
+
nodes {
|
|
1047
|
+
id
|
|
1048
|
+
code
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
codesCount {
|
|
1052
|
+
count
|
|
1053
|
+
precision
|
|
1054
|
+
}
|
|
1055
|
+
combinesWith {
|
|
1056
|
+
orderDiscounts
|
|
1057
|
+
productDiscounts
|
|
1058
|
+
shippingDiscounts
|
|
1059
|
+
}
|
|
1060
|
+
createdAt
|
|
1061
|
+
customerBuys {
|
|
1062
|
+
items {
|
|
1063
|
+
__typename
|
|
1064
|
+
... on AllDiscountItems {
|
|
1065
|
+
allItems
|
|
1066
|
+
}
|
|
1067
|
+
... on DiscountCollections {
|
|
1068
|
+
collectionsFirst250: collections(first: 250) {
|
|
1069
|
+
nodes {
|
|
1070
|
+
id
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
... on DiscountProducts {
|
|
1075
|
+
productsFirst250: products(first: 250) {
|
|
1076
|
+
nodes {
|
|
1077
|
+
id
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
1081
|
+
nodes {
|
|
1082
|
+
id
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
value {
|
|
1088
|
+
__typename
|
|
1089
|
+
... on DiscountPurchaseAmount {
|
|
1090
|
+
amount
|
|
1091
|
+
}
|
|
1092
|
+
... on DiscountQuantity {
|
|
1093
|
+
quantity
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
customerGets {
|
|
1098
|
+
appliesOnOneTimePurchase
|
|
1099
|
+
appliesOnSubscription
|
|
1100
|
+
items {
|
|
1101
|
+
__typename
|
|
1102
|
+
... on AllDiscountItems {
|
|
1103
|
+
allItems
|
|
1104
|
+
}
|
|
1105
|
+
... on DiscountCollections {
|
|
1106
|
+
collectionsFirst250: collections(first: 250) {
|
|
1107
|
+
nodes {
|
|
1108
|
+
id
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
... on DiscountProducts {
|
|
1113
|
+
productsFirst250: products(first: 250) {
|
|
1114
|
+
nodes {
|
|
1115
|
+
id
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
1119
|
+
nodes {
|
|
1120
|
+
id
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
value {
|
|
1126
|
+
__typename
|
|
1127
|
+
... on DiscountAmount {
|
|
1128
|
+
amount {
|
|
1129
|
+
amount
|
|
1130
|
+
currencyCode
|
|
1131
|
+
}
|
|
1132
|
+
appliesOnEachItem
|
|
1133
|
+
}
|
|
1134
|
+
... on DiscountOnQuantity {
|
|
1135
|
+
effect {
|
|
1136
|
+
__typename
|
|
1137
|
+
... on DiscountAmount {
|
|
1138
|
+
amount {
|
|
1139
|
+
amount
|
|
1140
|
+
currencyCode
|
|
1141
|
+
}
|
|
1142
|
+
appliesOnEachItem
|
|
1143
|
+
}
|
|
1144
|
+
... on DiscountPercentage {
|
|
1145
|
+
percentage
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
quantity {
|
|
1149
|
+
quantity
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
... on DiscountPercentage {
|
|
1153
|
+
percentage
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
customerSelection {
|
|
1158
|
+
__typename
|
|
1159
|
+
... on DiscountCustomerAll {
|
|
1160
|
+
allCustomers
|
|
1161
|
+
}
|
|
1162
|
+
... on DiscountCustomerSegments {
|
|
1163
|
+
segments {
|
|
1164
|
+
creationDate
|
|
1165
|
+
id
|
|
1166
|
+
lastEditDate
|
|
1167
|
+
name
|
|
1168
|
+
query
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
... on DiscountCustomers {
|
|
1172
|
+
customers {
|
|
1173
|
+
id
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
discountClass
|
|
1178
|
+
endsAt
|
|
1179
|
+
hasTimelineComment
|
|
1180
|
+
shareableUrls {
|
|
1181
|
+
url
|
|
1182
|
+
title
|
|
1183
|
+
}
|
|
1184
|
+
startsAt
|
|
1185
|
+
status
|
|
1186
|
+
summary
|
|
1187
|
+
title
|
|
1188
|
+
totalSales {
|
|
1189
|
+
amount
|
|
1190
|
+
currencyCode
|
|
1191
|
+
}
|
|
1192
|
+
updatedAt
|
|
1193
|
+
usageLimit
|
|
1194
|
+
usesPerOrderLimit
|
|
1195
|
+
}
|
|
1196
|
+
... on DiscountCodeFreeShipping {
|
|
1197
|
+
appliesOncePerCustomer
|
|
1198
|
+
appliesOnOneTimePurchase
|
|
1199
|
+
appliesOnSubscription
|
|
1200
|
+
asyncUsageCount
|
|
1201
|
+
codesFirst250: codes(first: 250) {
|
|
1202
|
+
nodes {
|
|
1203
|
+
id
|
|
1204
|
+
code
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
codesCount {
|
|
1208
|
+
count
|
|
1209
|
+
precision
|
|
1210
|
+
}
|
|
1211
|
+
combinesWith {
|
|
1212
|
+
orderDiscounts
|
|
1213
|
+
productDiscounts
|
|
1214
|
+
shippingDiscounts
|
|
1215
|
+
}
|
|
1216
|
+
createdAt
|
|
1217
|
+
customerSelection {
|
|
1218
|
+
__typename
|
|
1219
|
+
... on DiscountCustomerAll {
|
|
1220
|
+
allCustomers
|
|
1221
|
+
}
|
|
1222
|
+
... on DiscountCustomerSegments {
|
|
1223
|
+
segments {
|
|
1224
|
+
creationDate
|
|
1225
|
+
id
|
|
1226
|
+
lastEditDate
|
|
1227
|
+
name
|
|
1228
|
+
query
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
... on DiscountCustomers {
|
|
1232
|
+
customers {
|
|
1233
|
+
id
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
destinationSelection {
|
|
1238
|
+
__typename
|
|
1239
|
+
... on DiscountCountries {
|
|
1240
|
+
countries
|
|
1241
|
+
includeRestOfWorld
|
|
1242
|
+
}
|
|
1243
|
+
... on DiscountCountryAll {
|
|
1244
|
+
allCountries
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
discountClass
|
|
1248
|
+
endsAt
|
|
1249
|
+
hasTimelineComment
|
|
1250
|
+
maximumShippingPrice {
|
|
1251
|
+
amount
|
|
1252
|
+
currencyCode
|
|
1253
|
+
}
|
|
1254
|
+
minimumRequirement {
|
|
1255
|
+
__typename
|
|
1256
|
+
... on DiscountMinimumQuantity {
|
|
1257
|
+
greaterThanOrEqualToQuantity
|
|
1258
|
+
}
|
|
1259
|
+
... on DiscountMinimumSubtotal {
|
|
1260
|
+
greaterThanOrEqualToSubtotal {
|
|
1261
|
+
amount
|
|
1262
|
+
currencyCode
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
recurringCycleLimit
|
|
1267
|
+
shareableUrls {
|
|
1268
|
+
targetItemImage {
|
|
1269
|
+
id
|
|
1270
|
+
url
|
|
1271
|
+
}
|
|
1272
|
+
targetType
|
|
1273
|
+
title
|
|
1274
|
+
url
|
|
1275
|
+
}
|
|
1276
|
+
shortSummary
|
|
1277
|
+
startsAt
|
|
1278
|
+
status
|
|
1279
|
+
summary
|
|
1280
|
+
title
|
|
1281
|
+
totalSales {
|
|
1282
|
+
amount
|
|
1283
|
+
currencyCode
|
|
1284
|
+
}
|
|
1285
|
+
updatedAt
|
|
1286
|
+
usageLimit
|
|
1287
|
+
}
|
|
1288
|
+
... on DiscountAutomaticApp {
|
|
1289
|
+
appDiscountType {
|
|
1290
|
+
app {
|
|
1291
|
+
apiKey
|
|
1292
|
+
}
|
|
1293
|
+
appBridge {
|
|
1294
|
+
createPath
|
|
1295
|
+
detailsPath
|
|
1296
|
+
}
|
|
1297
|
+
appKey
|
|
1298
|
+
description
|
|
1299
|
+
discountClass
|
|
1300
|
+
functionId
|
|
1301
|
+
targetType
|
|
1302
|
+
title
|
|
1303
|
+
}
|
|
1304
|
+
asyncUsageCount
|
|
1305
|
+
combinesWith {
|
|
1306
|
+
orderDiscounts
|
|
1307
|
+
productDiscounts
|
|
1308
|
+
shippingDiscounts
|
|
1309
|
+
}
|
|
1310
|
+
createdAt
|
|
1311
|
+
discountClass
|
|
1312
|
+
discountId
|
|
1313
|
+
startsAt
|
|
1314
|
+
endsAt
|
|
1315
|
+
errorHistory {
|
|
1316
|
+
errorsFirstOccurredAt
|
|
1317
|
+
firstOccurredAt
|
|
1318
|
+
hasBeenSharedSinceLastError
|
|
1319
|
+
hasSharedRecentErrors
|
|
1320
|
+
}
|
|
1321
|
+
status
|
|
1322
|
+
title
|
|
1323
|
+
updatedAt
|
|
1324
|
+
}
|
|
1325
|
+
... on DiscountAutomaticBasic {
|
|
1326
|
+
asyncUsageCount
|
|
1327
|
+
combinesWith {
|
|
1328
|
+
orderDiscounts
|
|
1329
|
+
productDiscounts
|
|
1330
|
+
shippingDiscounts
|
|
1331
|
+
}
|
|
1332
|
+
createdAt
|
|
1333
|
+
customerGets {
|
|
1334
|
+
appliesOnOneTimePurchase
|
|
1335
|
+
appliesOnSubscription
|
|
1336
|
+
items {
|
|
1337
|
+
__typename
|
|
1338
|
+
... on AllDiscountItems {
|
|
1339
|
+
allItems
|
|
1340
|
+
}
|
|
1341
|
+
... on DiscountCollections {
|
|
1342
|
+
collectionsFirst250: collections(first: 250) {
|
|
1343
|
+
nodes {
|
|
1344
|
+
id
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
... on DiscountProducts {
|
|
1349
|
+
productsFirst250: products(first: 250) {
|
|
1350
|
+
nodes {
|
|
1351
|
+
id
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
1355
|
+
nodes {
|
|
1356
|
+
id
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
value {
|
|
1362
|
+
__typename
|
|
1363
|
+
... on DiscountAmount {
|
|
1364
|
+
amount {
|
|
1365
|
+
amount
|
|
1366
|
+
currencyCode
|
|
1367
|
+
}
|
|
1368
|
+
appliesOnEachItem
|
|
1369
|
+
}
|
|
1370
|
+
... on DiscountOnQuantity {
|
|
1371
|
+
effect {
|
|
1372
|
+
__typename
|
|
1373
|
+
... on DiscountAmount {
|
|
1374
|
+
amount {
|
|
1375
|
+
amount
|
|
1376
|
+
currencyCode
|
|
1377
|
+
}
|
|
1378
|
+
appliesOnEachItem
|
|
1379
|
+
}
|
|
1380
|
+
... on DiscountPercentage {
|
|
1381
|
+
percentage
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
quantity {
|
|
1385
|
+
quantity
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
... on DiscountPercentage {
|
|
1389
|
+
percentage
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
discountClass
|
|
1394
|
+
endsAt
|
|
1395
|
+
minimumRequirement {
|
|
1396
|
+
__typename
|
|
1397
|
+
... on DiscountMinimumQuantity {
|
|
1398
|
+
greaterThanOrEqualToQuantity
|
|
1399
|
+
}
|
|
1400
|
+
... on DiscountMinimumSubtotal {
|
|
1401
|
+
greaterThanOrEqualToSubtotal {
|
|
1402
|
+
amount
|
|
1403
|
+
currencyCode
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
recurringCycleLimit
|
|
1408
|
+
shortSummary
|
|
1409
|
+
startsAt
|
|
1410
|
+
status
|
|
1411
|
+
summary
|
|
1412
|
+
title
|
|
1413
|
+
updatedAt
|
|
1414
|
+
}
|
|
1415
|
+
... on DiscountAutomaticBxgy {
|
|
1416
|
+
asyncUsageCount
|
|
1417
|
+
combinesWith {
|
|
1418
|
+
orderDiscounts
|
|
1419
|
+
productDiscounts
|
|
1420
|
+
shippingDiscounts
|
|
1421
|
+
}
|
|
1422
|
+
createdAt
|
|
1423
|
+
customerBuys {
|
|
1424
|
+
items {
|
|
1425
|
+
__typename
|
|
1426
|
+
... on AllDiscountItems {
|
|
1427
|
+
allItems
|
|
1428
|
+
}
|
|
1429
|
+
... on DiscountCollections {
|
|
1430
|
+
collectionsFirst250: collections(first: 250) {
|
|
1431
|
+
nodes {
|
|
1432
|
+
id
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
... on DiscountProducts {
|
|
1437
|
+
productsFirst250: products(first: 250) {
|
|
1438
|
+
nodes {
|
|
1439
|
+
id
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
1443
|
+
nodes {
|
|
1444
|
+
id
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
value {
|
|
1450
|
+
__typename
|
|
1451
|
+
... on DiscountPurchaseAmount {
|
|
1452
|
+
amount
|
|
1453
|
+
}
|
|
1454
|
+
... on DiscountQuantity {
|
|
1455
|
+
quantity
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
customerGets {
|
|
1460
|
+
appliesOnOneTimePurchase
|
|
1461
|
+
appliesOnSubscription
|
|
1462
|
+
items {
|
|
1463
|
+
__typename
|
|
1464
|
+
... on AllDiscountItems {
|
|
1465
|
+
allItems
|
|
1466
|
+
}
|
|
1467
|
+
... on DiscountCollections {
|
|
1468
|
+
collectionsFirst250: collections(first: 250) {
|
|
1469
|
+
nodes {
|
|
1470
|
+
id
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
... on DiscountProducts {
|
|
1475
|
+
productsFirst250: products(first: 250) {
|
|
1476
|
+
nodes {
|
|
1477
|
+
id
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
productVariantsFirst250: productVariants(first: 250) {
|
|
1481
|
+
nodes {
|
|
1482
|
+
id
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
value {
|
|
1488
|
+
__typename
|
|
1489
|
+
... on DiscountAmount {
|
|
1490
|
+
amount {
|
|
1491
|
+
amount
|
|
1492
|
+
currencyCode
|
|
1493
|
+
}
|
|
1494
|
+
appliesOnEachItem
|
|
1495
|
+
}
|
|
1496
|
+
... on DiscountOnQuantity {
|
|
1497
|
+
effect {
|
|
1498
|
+
__typename
|
|
1499
|
+
... on DiscountAmount {
|
|
1500
|
+
amount {
|
|
1501
|
+
amount
|
|
1502
|
+
currencyCode
|
|
1503
|
+
}
|
|
1504
|
+
appliesOnEachItem
|
|
1505
|
+
}
|
|
1506
|
+
... on DiscountPercentage {
|
|
1507
|
+
percentage
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
quantity {
|
|
1511
|
+
quantity
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
... on DiscountPercentage {
|
|
1515
|
+
percentage
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
discountClass
|
|
1520
|
+
endsAt
|
|
1521
|
+
startsAt
|
|
1522
|
+
status
|
|
1523
|
+
summary
|
|
1524
|
+
title
|
|
1525
|
+
updatedAt
|
|
1526
|
+
usesPerOrderLimit
|
|
1527
|
+
}
|
|
1528
|
+
... on DiscountAutomaticFreeShipping {
|
|
1529
|
+
appliesOnOneTimePurchase
|
|
1530
|
+
appliesOnSubscription
|
|
1531
|
+
asyncUsageCount
|
|
1532
|
+
combinesWith {
|
|
1533
|
+
orderDiscounts
|
|
1534
|
+
productDiscounts
|
|
1535
|
+
shippingDiscounts
|
|
1536
|
+
}
|
|
1537
|
+
createdAt
|
|
1538
|
+
destinationSelection
|
|
1539
|
+
discountClass
|
|
1540
|
+
endsAt
|
|
1541
|
+
hasTimelineComment
|
|
1542
|
+
maximumShippingPrice {
|
|
1543
|
+
amount
|
|
1544
|
+
currencyCode
|
|
1545
|
+
}
|
|
1546
|
+
minimumRequirement {
|
|
1547
|
+
__typename
|
|
1548
|
+
... on DiscountMinimumQuantity {
|
|
1549
|
+
greaterThanOrEqualToQuantity
|
|
1550
|
+
}
|
|
1551
|
+
... on DiscountMinimumSubtotal {
|
|
1552
|
+
greaterThanOrEqualToSubtotal {
|
|
1553
|
+
amount
|
|
1554
|
+
currencyCode
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
recurringCycleLimit
|
|
1559
|
+
shortSummary
|
|
1560
|
+
startsAt
|
|
1561
|
+
status
|
|
1562
|
+
summary
|
|
1563
|
+
title
|
|
1564
|
+
totalSales {
|
|
1565
|
+
amount
|
|
1566
|
+
currencyCode
|
|
1567
|
+
}
|
|
1568
|
+
updatedAt
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
metafieldsFirst250: metafields(first: 250) {
|
|
1572
|
+
nodes {
|
|
1573
|
+
id
|
|
1574
|
+
key
|
|
1575
|
+
value
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
pageInfo {
|
|
1580
|
+
endCursor
|
|
1581
|
+
hasNextPage
|
|
1582
|
+
hasPreviousPage
|
|
1583
|
+
startCursor
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
"""
|
|
1588
|
+
|
|
1589
|
+
yield from client.get_graphql_pages(
|
|
1590
|
+
query,
|
|
1591
|
+
data_items_path="data.discountNodes.nodes[*]",
|
|
1592
|
+
pagination_cursor_path="data.discountNodes.pageInfo.endCursor",
|
|
1593
|
+
pagination_variable_name="after",
|
|
1594
|
+
variables={
|
|
1595
|
+
"first": items_per_page,
|
|
1596
|
+
},
|
|
1597
|
+
)
|
|
1598
|
+
|
|
1599
|
+
@dlt.resource(primary_key="id", write_disposition="merge")
|
|
1600
|
+
def taxonomy(items_per_page: int = items_per_page) -> Iterable[TDataItem]:
|
|
1601
|
+
client = ShopifyGraphQLApi(
|
|
1602
|
+
base_url=shop_url,
|
|
1603
|
+
access_token=private_app_password,
|
|
1604
|
+
api_version="2024-07",
|
|
1605
|
+
)
|
|
1606
|
+
|
|
1607
|
+
query = """
|
|
1608
|
+
{
|
|
1609
|
+
taxonomy {
|
|
1610
|
+
categories(first: 250) {
|
|
1611
|
+
nodes {
|
|
1612
|
+
id
|
|
1613
|
+
isArchived
|
|
1614
|
+
isLeaf
|
|
1615
|
+
isRoot
|
|
1616
|
+
level
|
|
1617
|
+
name
|
|
1618
|
+
parentId
|
|
1619
|
+
fullName
|
|
1620
|
+
ancestorIds
|
|
1621
|
+
attributes(first: 250) {
|
|
1622
|
+
nodes {
|
|
1623
|
+
... on TaxonomyAttribute {
|
|
1624
|
+
id
|
|
1625
|
+
}
|
|
1626
|
+
... on TaxonomyChoiceListAttribute {
|
|
1627
|
+
id
|
|
1628
|
+
name
|
|
1629
|
+
}
|
|
1630
|
+
... on TaxonomyMeasurementAttribute {
|
|
1631
|
+
id
|
|
1632
|
+
name
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
pageInfo {
|
|
1638
|
+
endCursor
|
|
1639
|
+
hasNextPage
|
|
1640
|
+
hasPreviousPage
|
|
1641
|
+
startCursor
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
"""
|
|
1647
|
+
|
|
1648
|
+
yield from client.get_graphql_pages(
|
|
1649
|
+
query,
|
|
1650
|
+
data_items_path="data.taxonomy.categories.nodes[*]",
|
|
1651
|
+
pagination_cursor_path="data.taxonomy.categories.pageInfo.endCursor",
|
|
1652
|
+
pagination_cursor_has_next_page_path="data.taxonomy.categories.pageInfo.hasNextPage",
|
|
1653
|
+
pagination_variable_name="after",
|
|
1654
|
+
variables={
|
|
1655
|
+
"first": items_per_page,
|
|
1656
|
+
},
|
|
1657
|
+
)
|
|
1658
|
+
|
|
1659
|
+
@dlt.resource(
|
|
1660
|
+
primary_key="id",
|
|
1661
|
+
write_disposition="merge",
|
|
1662
|
+
columns={
|
|
1663
|
+
"id": {
|
|
1664
|
+
"data_type": "text",
|
|
1665
|
+
"nullable": False,
|
|
1666
|
+
"primary_key": True,
|
|
1667
|
+
"description": "A globally unique ID for the product.",
|
|
1668
|
+
},
|
|
1669
|
+
"category": {
|
|
1670
|
+
"data_type": "complex",
|
|
1671
|
+
"nullable": True,
|
|
1672
|
+
"description": "The category of the product from Shopify's Standard Product Taxonomy.",
|
|
1673
|
+
},
|
|
1674
|
+
"combinedListing": {
|
|
1675
|
+
"data_type": "complex",
|
|
1676
|
+
"nullable": True,
|
|
1677
|
+
"description": "A special product type that combines separate products into a single product listing.",
|
|
1678
|
+
},
|
|
1679
|
+
"combinedListingRole": {
|
|
1680
|
+
"data_type": "complex",
|
|
1681
|
+
"nullable": True,
|
|
1682
|
+
"description": "The role of the product in a combined listing.",
|
|
1683
|
+
},
|
|
1684
|
+
"compareAtPriceRange": {
|
|
1685
|
+
"data_type": "complex",
|
|
1686
|
+
"nullable": True,
|
|
1687
|
+
"description": "The compare-at price range of the product in the shop's default currency.",
|
|
1688
|
+
},
|
|
1689
|
+
"createdAt": {
|
|
1690
|
+
"data_type": "timestamp",
|
|
1691
|
+
"nullable": False,
|
|
1692
|
+
"description": "The date and time when the product was created.",
|
|
1693
|
+
},
|
|
1694
|
+
"defaultCursor": {
|
|
1695
|
+
"data_type": "text",
|
|
1696
|
+
"nullable": False,
|
|
1697
|
+
"description": "A default cursor that returns the next record sorted by ID.",
|
|
1698
|
+
},
|
|
1699
|
+
"description": {
|
|
1700
|
+
"data_type": "text",
|
|
1701
|
+
"nullable": False,
|
|
1702
|
+
"description": "A single-line description of the product, with HTML tags removed.",
|
|
1703
|
+
},
|
|
1704
|
+
"descriptionHtml": {
|
|
1705
|
+
"data_type": "text",
|
|
1706
|
+
"nullable": False,
|
|
1707
|
+
"description": "The description of the product, with HTML tags.",
|
|
1708
|
+
},
|
|
1709
|
+
"handle": {
|
|
1710
|
+
"data_type": "text",
|
|
1711
|
+
"nullable": False,
|
|
1712
|
+
"description": "A unique, human-readable string of the product's title.",
|
|
1713
|
+
},
|
|
1714
|
+
"metafields": {
|
|
1715
|
+
"data_type": "complex",
|
|
1716
|
+
"nullable": True,
|
|
1717
|
+
"description": "A list of custom fields associated with the product.",
|
|
1718
|
+
},
|
|
1719
|
+
"options": {
|
|
1720
|
+
"data_type": "complex",
|
|
1721
|
+
"nullable": True,
|
|
1722
|
+
"description": "A list of product options, e.g., size, color.",
|
|
1723
|
+
},
|
|
1724
|
+
"priceRangeV2": {
|
|
1725
|
+
"data_type": "complex",
|
|
1726
|
+
"nullable": False,
|
|
1727
|
+
"description": "The minimum and maximum prices of a product.",
|
|
1728
|
+
},
|
|
1729
|
+
"productType": {
|
|
1730
|
+
"data_type": "text",
|
|
1731
|
+
"nullable": False,
|
|
1732
|
+
"description": "The product type defined by the merchant.",
|
|
1733
|
+
},
|
|
1734
|
+
"publishedAt": {
|
|
1735
|
+
"data_type": "timestamp",
|
|
1736
|
+
"nullable": True,
|
|
1737
|
+
"description": "The date and time when the product was published.",
|
|
1738
|
+
},
|
|
1739
|
+
"status": {
|
|
1740
|
+
"data_type": "text",
|
|
1741
|
+
"nullable": False,
|
|
1742
|
+
"description": "The product status, which controls visibility across all sales channels.",
|
|
1743
|
+
},
|
|
1744
|
+
"tags": {
|
|
1745
|
+
"data_type": "text",
|
|
1746
|
+
"nullable": True,
|
|
1747
|
+
"description": "A comma-separated list of searchable keywords associated with the product.",
|
|
1748
|
+
},
|
|
1749
|
+
"templateSuffix": {
|
|
1750
|
+
"data_type": "text",
|
|
1751
|
+
"nullable": True,
|
|
1752
|
+
"description": "The theme template used when customers view the product in a store.",
|
|
1753
|
+
},
|
|
1754
|
+
"title": {
|
|
1755
|
+
"data_type": "text",
|
|
1756
|
+
"nullable": False,
|
|
1757
|
+
"description": "The name for the product that displays to customers.",
|
|
1758
|
+
},
|
|
1759
|
+
"totalInventory": {
|
|
1760
|
+
"data_type": "bigint",
|
|
1761
|
+
"nullable": False,
|
|
1762
|
+
"description": "The quantity of inventory that's in stock.",
|
|
1763
|
+
},
|
|
1764
|
+
"totalVariants": {
|
|
1765
|
+
"data_type": "bigint",
|
|
1766
|
+
"nullable": False,
|
|
1767
|
+
"description": "The number of variants associated with the product.",
|
|
1768
|
+
},
|
|
1769
|
+
"tracksInventory": {
|
|
1770
|
+
"data_type": "bool",
|
|
1771
|
+
"nullable": False,
|
|
1772
|
+
"description": "Whether inventory tracking is enabled for the product.",
|
|
1773
|
+
},
|
|
1774
|
+
"updatedAt": {
|
|
1775
|
+
"data_type": "timestamp",
|
|
1776
|
+
"nullable": False,
|
|
1777
|
+
"description": "The date and time when the product was last modified.",
|
|
1778
|
+
},
|
|
1779
|
+
"vendor": {
|
|
1780
|
+
"data_type": "text",
|
|
1781
|
+
"nullable": False,
|
|
1782
|
+
"description": "The name of the product's vendor.",
|
|
1783
|
+
},
|
|
1784
|
+
},
|
|
219
1785
|
)
|
|
1786
|
+
def products(
|
|
1787
|
+
updated_at: dlt.sources.incremental[
|
|
1788
|
+
pendulum.DateTime
|
|
1789
|
+
] = dlt.sources.incremental(
|
|
1790
|
+
"updatedAt",
|
|
1791
|
+
initial_value=start_date_obj,
|
|
1792
|
+
end_value=end_date_obj,
|
|
1793
|
+
),
|
|
1794
|
+
items_per_page: int = items_per_page,
|
|
1795
|
+
) -> Iterable[TDataItem]:
|
|
1796
|
+
client = ShopifyGraphQLApi(
|
|
1797
|
+
base_url=shop_url,
|
|
1798
|
+
access_token=private_app_password,
|
|
1799
|
+
api_version="2024-07",
|
|
1800
|
+
)
|
|
1801
|
+
|
|
1802
|
+
query = """
|
|
1803
|
+
query products($after: String, $query: String, $first: Int) {
|
|
1804
|
+
products(after: $after, first: $first, query: $query) {
|
|
1805
|
+
nodes {
|
|
1806
|
+
availablePublicationsCount {
|
|
1807
|
+
count
|
|
1808
|
+
precision
|
|
1809
|
+
}
|
|
1810
|
+
category {
|
|
1811
|
+
id
|
|
1812
|
+
}
|
|
1813
|
+
combinedListing {
|
|
1814
|
+
parentProduct {
|
|
1815
|
+
id
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
combinedListingRole
|
|
1819
|
+
compareAtPriceRange {
|
|
1820
|
+
maxVariantCompareAtPrice {
|
|
1821
|
+
amount
|
|
1822
|
+
currencyCode
|
|
1823
|
+
}
|
|
1824
|
+
minVariantCompareAtPrice {
|
|
1825
|
+
amount
|
|
1826
|
+
currencyCode
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
createdAt
|
|
1830
|
+
defaultCursor
|
|
1831
|
+
description
|
|
1832
|
+
descriptionHtml
|
|
1833
|
+
handle
|
|
1834
|
+
id
|
|
1835
|
+
metafields(first: 250) {
|
|
1836
|
+
nodes {
|
|
1837
|
+
id
|
|
1838
|
+
key
|
|
1839
|
+
value
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
options {
|
|
1843
|
+
linkedMetafield {
|
|
1844
|
+
key
|
|
1845
|
+
namespace
|
|
1846
|
+
}
|
|
1847
|
+
name
|
|
1848
|
+
optionValues {
|
|
1849
|
+
hasVariants
|
|
1850
|
+
id
|
|
1851
|
+
linkedMetafieldValue
|
|
1852
|
+
name
|
|
1853
|
+
}
|
|
1854
|
+
values
|
|
1855
|
+
id
|
|
1856
|
+
position
|
|
1857
|
+
}
|
|
1858
|
+
priceRangeV2 {
|
|
1859
|
+
maxVariantPrice {
|
|
1860
|
+
amount
|
|
1861
|
+
currencyCode
|
|
1862
|
+
}
|
|
1863
|
+
minVariantPrice {
|
|
1864
|
+
amount
|
|
1865
|
+
currencyCode
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
productType
|
|
1869
|
+
publishedAt
|
|
1870
|
+
requiresSellingPlan
|
|
1871
|
+
status
|
|
1872
|
+
tags
|
|
1873
|
+
templateSuffix
|
|
1874
|
+
totalInventory
|
|
1875
|
+
title
|
|
1876
|
+
tracksInventory
|
|
1877
|
+
updatedAt
|
|
1878
|
+
vendor
|
|
1879
|
+
variantsCount {
|
|
1880
|
+
count
|
|
1881
|
+
precision
|
|
1882
|
+
}
|
|
1883
|
+
variants(first: 250) {
|
|
1884
|
+
nodes {
|
|
1885
|
+
id
|
|
1886
|
+
sku
|
|
1887
|
+
storefrontId
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
pageInfo {
|
|
1892
|
+
endCursor
|
|
1893
|
+
hasNextPage
|
|
1894
|
+
hasPreviousPage
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
"""
|
|
1899
|
+
variables = {
|
|
1900
|
+
"first": items_per_page,
|
|
1901
|
+
"query": f"updated_at:>'{updated_at.last_value.isoformat()}'",
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
yield from client.get_graphql_pages(
|
|
1905
|
+
query,
|
|
1906
|
+
data_items_path="data.products.nodes[*]",
|
|
1907
|
+
pagination_cursor_path="data.products.pageInfo.endCursor",
|
|
1908
|
+
pagination_cursor_has_next_page_path="data.products.pageInfo.hasNextPage",
|
|
1909
|
+
pagination_variable_name="after",
|
|
1910
|
+
variables=variables,
|
|
1911
|
+
)
|
|
220
1912
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
1913
|
+
return (
|
|
1914
|
+
products,
|
|
1915
|
+
products_legacy,
|
|
1916
|
+
orders,
|
|
1917
|
+
customers,
|
|
1918
|
+
inventory_items,
|
|
1919
|
+
transactions,
|
|
1920
|
+
balance,
|
|
1921
|
+
events,
|
|
1922
|
+
price_rules,
|
|
1923
|
+
discounts,
|
|
1924
|
+
taxonomy,
|
|
227
1925
|
)
|