Coverage for mindsdb / integrations / handlers / shopify_handler / shopify_tables.py: 0%
218 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1import json
2from typing import List, Dict
4import shopify
5import pandas as pd
7from mindsdb.integrations.libs.api_handler import MetaAPIResource
8from mindsdb.integrations.utilities.sql_utils import FilterCondition, FilterOperator, SortColumn
9from mindsdb.utilities import log
11from .utils import query_graphql_nodes, get_graphql_columns, _format_error
12from .models.products import Products, columns as products_columns
13from .models.product_variants import ProductVariants, columns as product_variants_columns
14from .models.customers import Customers, columns as customers_columns
15from .models.orders import Orders, columns as orders_columns
16from .models.marketing_events import MarketingEvents, columns as marketing_events_columns
17from .models.inventory_items import InventoryItems, columns as inventory_items_columns
18from .models.staff_members import StaffMembers, columns as staff_members_columns
19from .models.gift_cards import GiftCards, columns as gift_cards_columns
21logger = log.getLogger(__name__)
24class ShopifyMetaAPIResource(MetaAPIResource):
25 """A class to represent a Shopify Meta API resource."""
27 def list(
28 self,
29 conditions: list[FilterCondition] | None = None,
30 limit: int | None = None,
31 sort: list[SortColumn] | None = None,
32 targets: list[str] | None = None,
33 **kwargs,
34 ):
35 """Query the Shopify API to get the resources data.
37 Args:
38 conditions: The conditions to apply to the query.
39 limit: The limit of the resources to return.
40 sort: The sort to apply to the query.
41 targets: The columns to include in the query.
43 Returns:
44 pd.DataFrame: The data of the resources.
45 """
46 sort_key, sort_reverse = self._get_sort(sort)
47 query_conditions = self._get_query_conditions(conditions)
49 api_session = self.handler.connect()
50 shopify.ShopifyResource.activate_session(api_session)
52 columns = get_graphql_columns(self.model, targets)
53 data = query_graphql_nodes(
54 self.model_name,
55 self.model,
56 columns,
57 sort_key=sort_key,
58 sort_reverse=sort_reverse,
59 query=query_conditions,
60 limit=limit,
61 )
63 if len(data) == 0:
64 df_columns = targets
65 if targets is None or len(targets) == 0:
66 df_columns = [column.name for column in self.model]
67 products_df = pd.DataFrame(data, columns=df_columns)
68 else:
69 products_df = pd.DataFrame(data)
71 return products_df
73 def _get_sort(self, sort: List[SortColumn] | None) -> tuple[str, bool]:
74 """Get the sort key and reverse from the sort list.
76 Args:
77 sort: The sort list.
79 Returns:
80 tuple[str, bool]: The sort key and reverse flag.
81 """
82 sort_key = None
83 sort_reverse = None
84 sort_map = self.sort_map or {}
85 if sort:
86 order_by = sort[0].column.lower()
87 asc = sort[0].ascending
88 if order_by not in sort_map:
89 logger.info(
90 f"Used unsupported column for order by: {order_by}, available columns are: {list(self.sort_map.keys())}."
91 )
92 return None, None
94 sort_key = sort_map[order_by]
95 sort_reverse = not asc
96 sort[0].applied = True
97 return sort_key, sort_reverse
99 def _get_query_conditions(self, conditions: List[FilterCondition] | None) -> str:
100 """Get the GraphQL query conditions from the conditions list.
102 Args:
103 conditions: The conditions list.
105 Returns:
106 str: The query conditions.
107 """
108 query_conditions = []
109 conditions_op_map = self.conditions_op_map or {}
110 for condition in conditions or []:
111 op = condition.op
112 column = condition.column.lower()
113 mapped_op = conditions_op_map.get((column, op))
114 if mapped_op:
115 value = condition.value
116 if isinstance(value, list):
117 value = ",".join(value)
118 elif isinstance(value, bool):
119 value = f"{value}".lower()
120 query_conditions.append(f"{mapped_op}{value}")
121 condition.applied = True
122 query_conditions = " AND ".join(query_conditions)
123 return query_conditions
125 def get_columns(self) -> List[str]:
126 """Get the table columns names.
128 Returns:
129 List[str]: The columns names.
130 """
131 return [column["COLUMN_NAME"] for column in self.columns]
133 def meta_get_columns(self, *args, **kwargs) -> List[dict]:
134 """Get the table columns metadata.
136 Returns:
137 List[dict]: The columns metadata.
138 """
139 return self.columns
141 def query_graphql(self, query: str) -> dict:
142 """Query the GraphQL API.
144 Args:
145 query: The GraphQL query to execute.
147 Returns:
148 dict: The result of the GraphQL query.
149 """
150 api_session = self.handler.connect()
151 shopify.ShopifyResource.activate_session(api_session)
152 result = shopify.GraphQL().execute(query)
153 result = json.loads(result)
154 if "errors" in result:
155 raise Exception(_format_error(result["errors"]))
156 return result
159class ProductsTable(ShopifyMetaAPIResource):
160 """The Shopify Products Table implementation
161 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/products
162 """
164 def __init__(self, *args, **kwargs):
165 self.name = "products"
166 self.model = Products
167 self.model_name = "products"
168 self.columns = products_columns
170 sort_map = {
171 Products.createdAt: "CREATED_AT",
172 Products.id: "ID",
173 Products.totalInventory: "INVENTORY_TOTAL",
174 Products.productType: "PRODUCT_TYPE",
175 Products.publishedAt: "PUBLISHED_AT",
176 Products.title: "TITLE",
177 Products.updatedAt: "UPDATED_AT",
178 Products.vendor: "VENDOR",
179 }
180 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
182 self.conditions_op_map = {
183 ("createdat", FilterOperator.GREATER_THAN): "created_at:>",
184 ("createdat", FilterOperator.GREATER_THAN_OR_EQUAL): "created_at:>=",
185 ("createdat", FilterOperator.LESS_THAN): "created_at:<",
186 ("createdat", FilterOperator.LESS_THAN_OR_EQUAL): "created_at:<=",
187 ("createdat", FilterOperator.EQUAL): "created_at:",
188 ("id", FilterOperator.GREATER_THAN): "id:>",
189 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
190 ("id", FilterOperator.LESS_THAN): "id:<",
191 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
192 ("id", FilterOperator.EQUAL): "id:",
193 ("isgiftcard", FilterOperator.EQUAL): "gift_card:",
194 ("handle", FilterOperator.EQUAL): "handle:",
195 ("handle", FilterOperator.IN): "handle:",
196 ("totalinventory", FilterOperator.EQUAL): "inventory_total:",
197 ("producttype", FilterOperator.EQUAL): "product_type:",
198 ("producttype", FilterOperator.IN): "product_type:",
199 ("publishedat", FilterOperator.GREATER_THAN): "published_at:>",
200 ("publishedat", FilterOperator.GREATER_THAN_OR_EQUAL): "published_at:>=",
201 ("publishedat", FilterOperator.LESS_THAN): "published_at:<",
202 ("publishedat", FilterOperator.LESS_THAN_OR_EQUAL): "published_at:<=",
203 ("publishedat", FilterOperator.EQUAL): "published_at:",
204 ("status", FilterOperator.EQUAL): "status:",
205 ("status", FilterOperator.IN): "status:",
206 ("title", FilterOperator.EQUAL): "title:",
207 ("updatedat", FilterOperator.GREATER_THAN): "updated_at:>",
208 ("updatedat", FilterOperator.GREATER_THAN_OR_EQUAL): "updated_at:>=",
209 ("updatedat", FilterOperator.LESS_THAN): "updated_at:<",
210 ("updatedat", FilterOperator.LESS_THAN_OR_EQUAL): "updated_at:<=",
211 ("updatedat", FilterOperator.EQUAL): "updated_at:",
212 ("vendor", FilterOperator.EQUAL): "vendor:",
213 }
214 super().__init__(*args, **kwargs)
216 def meta_get_tables(self, *args, **kwargs) -> dict:
217 response = self.query_graphql("""{
218 productsCount(limit:null) {
219 count
220 } }""")
221 row_count = response["data"]["productsCount"]["count"]
223 return {
224 "table_name": self.name,
225 "table_type": "BASE TABLE",
226 "table_description": "List of products. Products are the items that merchants can sell in their store.",
227 "row_count": row_count,
228 }
230 def meta_get_primary_keys(self, table_name: str) -> list[Dict]:
231 return [
232 {
233 "table_name": table_name,
234 "column_name": "id",
235 }
236 ]
238 def meta_get_foreign_keys(self, table_name: str, all_tables: list[str]) -> list[Dict]:
239 return []
242class ProductVariantsTable(ShopifyMetaAPIResource):
243 """The Shopify Product Variants Table implementation
244 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/productvariants
245 """
247 def __init__(self, *args, **kwargs):
248 self.name = "product_variants"
249 self.model = ProductVariants
250 self.model_name = "productVariants"
251 self.columns = product_variants_columns
253 sort_map = {
254 ProductVariants.id: "ID",
255 ProductVariants.inventoryQuantity: "INVENTORY_QUANTITY",
256 ProductVariants.displayName: "NAME",
257 ProductVariants.position: "POSITION",
258 ProductVariants.sku: "SKU",
259 ProductVariants.title: "TITLE",
260 }
261 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
263 self.conditions_op_map = {
264 ("barcode", FilterOperator.EQUAL): "barcode:",
265 ("id", FilterOperator.GREATER_THAN): "id:>",
266 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
267 ("id", FilterOperator.LESS_THAN): "id:<",
268 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
269 ("id", FilterOperator.EQUAL): "id:",
270 ("inventoryquantity", FilterOperator.GREATER_THAN): "inventoryquantity:>",
271 ("inventoryquantity", FilterOperator.GREATER_THAN_OR_EQUAL): "inventoryquantity:>=",
272 ("inventoryquantity", FilterOperator.LESS_THAN): "inventoryquantity:<",
273 ("inventoryquantity", FilterOperator.LESS_THAN_OR_EQUAL): "inventoryquantity:<=",
274 ("inventoryquantity", FilterOperator.EQUAL): "inventoryquantity:",
275 ("productid", FilterOperator.GREATER_THAN): "product_id:>",
276 ("productid", FilterOperator.GREATER_THAN_OR_EQUAL): "product_id:>=",
277 ("productid", FilterOperator.LESS_THAN): "product_id:<",
278 ("productid", FilterOperator.LESS_THAN_OR_EQUAL): "product_id:<=",
279 ("productid", FilterOperator.EQUAL): "product_id:",
280 ("productid", FilterOperator.IN): "toproduct_ids:",
281 ("sku", FilterOperator.EQUAL): "sku:",
282 ("title", FilterOperator.EQUAL): "title:",
283 ("updatedat", FilterOperator.GREATER_THAN): "updated_at:>",
284 ("updatedat", FilterOperator.GREATER_THAN_OR_EQUAL): "updated_at:>=",
285 ("updatedat", FilterOperator.LESS_THAN): "updated_at:<",
286 ("updatedat", FilterOperator.LESS_THAN_OR_EQUAL): "updated_at:<=",
287 ("updatedat", FilterOperator.EQUAL): "updated_at:",
288 }
289 super().__init__(*args, **kwargs)
291 def meta_get_tables(self, *args, **kwargs) -> dict:
292 response = self.query_graphql("""{
293 productVariantsCount(limit:null) {
294 count
295 } }""")
296 row_count = response["data"]["productVariantsCount"]["count"]
298 return {
299 "table_name": self.name,
300 "table_type": "BASE TABLE",
301 "table_description": "List of product variants. A product variant is a specific version of a product that comes in more than one option, such as size or color.",
302 "row_count": row_count,
303 }
305 def meta_get_primary_keys(self, table_name: str) -> list[Dict]:
306 return [
307 {
308 "table_name": table_name,
309 "column_name": "id",
310 }
311 ]
313 def meta_get_foreign_keys(self, table_name: str, all_tables: list[str]) -> list[Dict]:
314 return [
315 {
316 "PARENT_TABLE_NAME": table_name,
317 "PARENT_COLUMN_NAME": "productId",
318 "CHILD_TABLE_NAME": "products",
319 "CHILD_COLUMN_NAME": "id",
320 }
321 ]
324class CustomersTable(ShopifyMetaAPIResource):
325 """The Shopify Customers Table implementation
326 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/customers
327 """
329 def __init__(self, *args, **kwargs):
330 self.name = "customers"
331 self.model = Customers
332 self.model_name = "customers"
333 self.columns = customers_columns
335 sort_map = {
336 Customers.createdAt: "CREATED_AT",
337 Customers.id: "ID",
338 Customers.updatedAt: "UPDATED_AT",
339 }
340 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
342 self.conditions_op_map = {
343 ("country", FilterOperator.EQUAL): "country:",
344 ("createdat", FilterOperator.GREATER_THAN): "customer_date:>",
345 ("createdat", FilterOperator.GREATER_THAN_OR_EQUAL): "customer_date:>=",
346 ("createdat", FilterOperator.LESS_THAN): "customer_date:<",
347 ("createdat", FilterOperator.LESS_THAN_OR_EQUAL): "customer_date:<=",
348 ("createdat", FilterOperator.EQUAL): "customer_date:",
349 ("email", FilterOperator.EQUAL): "email:",
350 ("firstname", FilterOperator.EQUAL): "first_name:",
351 ("id", FilterOperator.GREATER_THAN): "id:>",
352 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
353 ("id", FilterOperator.LESS_THAN): "id:<",
354 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
355 ("id", FilterOperator.EQUAL): "id:",
356 ("lastname", FilterOperator.EQUAL): "last_name:",
357 ("phonenumber", FilterOperator.EQUAL): "phone:",
358 ("updatedat", FilterOperator.GREATER_THAN): "updated_at:>",
359 ("updatedat", FilterOperator.GREATER_THAN_OR_EQUAL): "updated_at:>=",
360 ("updatedat", FilterOperator.LESS_THAN): "updated_at:<",
361 ("updatedat", FilterOperator.LESS_THAN_OR_EQUAL): "updated_at:<=",
362 ("updatedat", FilterOperator.EQUAL): "updated_at:",
363 }
364 super().__init__(*args, **kwargs)
366 def meta_get_tables(self, *args, **kwargs) -> dict:
367 response = self.query_graphql("""{
368 customersCount(limit:null) {
369 count
370 } }""")
371 row_count = response["data"]["customersCount"]["count"]
373 return {
374 "table_name": self.name,
375 "table_type": "BASE TABLE",
376 "table_description": "List of customers in your Shopify store, including key information such as name, email, location, and purchase history",
377 "row_count": row_count,
378 }
380 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
381 return [
382 {
383 "table_name": table_name,
384 "column_name": "id",
385 }
386 ]
388 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
389 return []
392class OrdersTable(ShopifyMetaAPIResource):
393 """The Shopify Orders Table implementation
394 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/orders
395 """
397 def __init__(self, *args, **kwargs):
398 self.name = "orders"
399 self.model = Orders
400 self.model_name = "orders"
401 self.columns = orders_columns
403 sort_map = {
404 Orders.createdAt: "CREATED_AT",
405 Orders.id: "ID",
406 Orders.number: "ORDER_NUMBER",
407 Orders.poNumber: "PO_NUMBER",
408 Orders.processedAt: "PROCESSED_AT",
409 Orders.updatedAt: "UPDATED_AT",
410 }
411 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
413 self.conditions_op_map = {
414 ("confirmationnumber", FilterOperator.EQUAL): "confirmation_number:",
415 ("createdat", FilterOperator.GREATER_THAN): "created_at:>",
416 ("createdat", FilterOperator.GREATER_THAN_OR_EQUAL): "created_at:>=",
417 ("createdat", FilterOperator.LESS_THAN): "created_at:<",
418 ("createdat", FilterOperator.LESS_THAN_OR_EQUAL): "created_at:<=",
419 ("createdat", FilterOperator.EQUAL): "created_at:",
420 ("customerid", FilterOperator.EQUAL): "customer_id:",
421 ("discountcode", FilterOperator.EQUAL): "discount_code:",
422 ("email", FilterOperator.EQUAL): "email:",
423 ("id", FilterOperator.GREATER_THAN): "id:>",
424 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
425 ("id", FilterOperator.LESS_THAN): "id:<",
426 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
427 ("id", FilterOperator.EQUAL): "id:",
428 ("name", FilterOperator.EQUAL): "name:",
429 ("ponumber", FilterOperator.EQUAL): "po_number:",
430 ("processedat", FilterOperator.GREATER_THAN): "processed_at:>",
431 ("processedat", FilterOperator.GREATER_THAN_OR_EQUAL): "processed_at:>=",
432 ("processedat", FilterOperator.LESS_THAN): "processed_at:<",
433 ("processedat", FilterOperator.LESS_THAN_OR_EQUAL): "processed_at:<=",
434 ("processedat", FilterOperator.EQUAL): "processed_at:",
435 ("returnstatus", FilterOperator.EQUAL): "return_status:",
436 ("sourceidentifier", FilterOperator.EQUAL): "source_identifier:",
437 ("sourcename", FilterOperator.EQUAL): "source_name:",
438 ("test", FilterOperator.EQUAL): "test:",
439 ("totalweight", FilterOperator.GREATER_THAN): "total_weight:>",
440 ("totalweight", FilterOperator.GREATER_THAN_OR_EQUAL): "total_weight:>=",
441 ("totalweight", FilterOperator.LESS_THAN): "total_weight:<",
442 ("totalweight", FilterOperator.LESS_THAN_OR_EQUAL): "total_weight:<=",
443 ("totalweight", FilterOperator.EQUAL): "total_weight:",
444 ("updatedat", FilterOperator.GREATER_THAN): "updated_at:>",
445 ("updatedat", FilterOperator.GREATER_THAN_OR_EQUAL): "updated_at:>=",
446 ("updatedat", FilterOperator.LESS_THAN): "updated_at:<",
447 ("updatedat", FilterOperator.LESS_THAN_OR_EQUAL): "updated_at:<=",
448 ("updatedat", FilterOperator.EQUAL): "updated_at:",
449 }
450 super().__init__(*args, **kwargs)
452 def meta_get_tables(self, *args, **kwargs) -> dict:
453 response = self.query_graphql("""{
454 ordersCount(limit:null) {
455 count
456 } }""")
457 row_count = response["data"]["ordersCount"]["count"]
459 return {
460 "table_name": self.name,
461 "table_type": "BASE TABLE",
462 "table_description": "List of orders placed in the store, including data such as order status, customer, and line item details.",
463 "row_count": row_count,
464 }
466 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
467 return [
468 {
469 "table_name": table_name,
470 "column_name": "id",
471 }
472 ]
474 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
475 return [
476 {
477 "PARENT_TABLE_NAME": table_name,
478 "PARENT_COLUMN_NAME": "customerId",
479 "CHILD_TABLE_NAME": "customers",
480 "CHILD_COLUMN_NAME": "id",
481 }
482 ]
485class MarketingEventsTable(ShopifyMetaAPIResource):
486 """The Shopify MarketingEvents table implementation
487 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/marketingevents
488 """
490 def __init__(self, *args, **kwargs):
491 self.name = "marketing_events"
492 self.model = MarketingEvents
493 self.model_name = "marketingEvents"
494 self.columns = marketing_events_columns
496 sort_map = {
497 MarketingEvents.id: "ID",
498 MarketingEvents.startedAt: "STARTED_AT",
499 }
500 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
502 self.conditions_op_map = {
503 ("id", FilterOperator.GREATER_THAN): "id:>",
504 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
505 ("id", FilterOperator.LESS_THAN): "id:<",
506 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
507 ("id", FilterOperator.EQUAL): "id:",
508 ("startedat", FilterOperator.GREATER_THAN): "started_at:>",
509 ("startedat", FilterOperator.GREATER_THAN_OR_EQUAL): "started_at:>=",
510 ("startedat", FilterOperator.LESS_THAN): "started_at:<",
511 ("startedat", FilterOperator.LESS_THAN_OR_EQUAL): "started_at:<=",
512 ("startedat", FilterOperator.EQUAL): "started_at:",
513 ("description", FilterOperator.EQUAL): "description:",
514 ("description", FilterOperator.LIKE): "description:",
515 ("type", FilterOperator.EQUAL): "type:",
516 ("type", FilterOperator.LIKE): "type:",
517 }
518 super().__init__(*args, **kwargs)
520 def meta_get_tables(self, *args, **kwargs) -> dict:
521 data = query_graphql_nodes(
522 self.model_name,
523 self.model,
524 "id",
525 )
526 row_count = len(data)
528 return {
529 "table_name": self.name,
530 "table_type": "BASE TABLE",
531 "table_description": "A list of marketing events.",
532 "row_count": row_count,
533 }
535 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
536 return [
537 {
538 "table_name": table_name,
539 "column_name": "id",
540 }
541 ]
543 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
544 return []
547class InventoryItemsTable(ShopifyMetaAPIResource):
548 """The Shopify InventoryItems table implementation
549 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/inventoryitems
550 """
552 def __init__(self, *args, **kwargs):
553 self.name = "inventory_items"
554 self.model = InventoryItems
555 self.model_name = "inventoryItems"
556 self.columns = inventory_items_columns
558 self.sort_map = {}
560 self.conditions_op_map = {
561 ("id", FilterOperator.GREATER_THAN): "id:>",
562 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
563 ("id", FilterOperator.LESS_THAN): "id:<",
564 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
565 ("id", FilterOperator.EQUAL): "id:",
566 ("createdat", FilterOperator.GREATER_THAN): "created_at:>",
567 ("createdat", FilterOperator.GREATER_THAN_OR_EQUAL): "created_at:>=",
568 ("createdat", FilterOperator.LESS_THAN): "created_at:<",
569 ("createdat", FilterOperator.LESS_THAN_OR_EQUAL): "created_at:<=",
570 ("createdat", FilterOperator.EQUAL): "created_at:",
571 ("sku", FilterOperator.EQUAL): "sku:",
572 ("updatedat", FilterOperator.GREATER_THAN): "updated_at:>",
573 ("updatedat", FilterOperator.GREATER_THAN_OR_EQUAL): "updated_at:>=",
574 ("updatedat", FilterOperator.LESS_THAN): "updated_at:<",
575 ("updatedat", FilterOperator.LESS_THAN_OR_EQUAL): "updated_at:<=",
576 ("updatedat", FilterOperator.EQUAL): "updated_at:",
577 }
578 super().__init__(*args, **kwargs)
580 def meta_get_tables(self, *args, **kwargs) -> dict:
581 data = query_graphql_nodes(
582 self.model_name,
583 self.model,
584 "id",
585 )
586 row_count = len(data)
588 return {
589 "table_name": self.name,
590 "table_type": "BASE TABLE",
591 "table_description": "A list of inventory items.",
592 "row_count": row_count,
593 }
595 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
596 return [
597 {
598 "table_name": table_name,
599 "column_name": "id",
600 }
601 ]
603 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
604 return []
607class StaffMembersTable(ShopifyMetaAPIResource):
608 """The Shopify StaffMembers table implementation
609 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/staffmembers
610 """
612 def __init__(self, *args, **kwargs):
613 self.name = "staff_members"
614 self.model = StaffMembers
615 self.model_name = "staffMembers"
616 self.columns = staff_members_columns
618 sort_map = {
619 StaffMembers.id: "ID",
620 StaffMembers.email: "EMAIL",
621 StaffMembers.firstName: "FIRST_NAME",
622 StaffMembers.lastName: "LAST_NAME",
623 }
624 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
626 self.conditions_op_map = {
627 ("accounttype", FilterOperator.EQUAL): "account_type:",
628 ("email", FilterOperator.EQUAL): "email:",
629 ("firstname", FilterOperator.EQUAL): "first_name:",
630 ("firstname", FilterOperator.LIKE): "first_name:",
631 ("lastname", FilterOperator.EQUAL): "last_name:",
632 ("lastname", FilterOperator.LIKE): "last_name:",
633 ("id", FilterOperator.GREATER_THAN): "id:>",
634 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
635 ("id", FilterOperator.LESS_THAN): "id:<",
636 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
637 ("id", FilterOperator.EQUAL): "id:",
638 }
639 super().__init__(*args, **kwargs)
641 def meta_get_tables(self, *args, **kwargs) -> dict:
642 data = query_graphql_nodes(
643 self.model_name,
644 self.model,
645 "id",
646 )
647 row_count = len(data)
649 return {
650 "table_name": self.name,
651 "table_type": "BASE TABLE",
652 "table_description": "The shop staff members.",
653 "row_count": row_count,
654 }
656 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
657 return [
658 {
659 "table_name": table_name,
660 "column_name": "id",
661 }
662 ]
664 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
665 return []
668class GiftCardsTable(ShopifyMetaAPIResource):
669 """The Shopify GiftCards table implementation
670 Reference: https://shopify.dev/docs/api/admin-graphql/latest/queries/giftcards
671 """
673 def __init__(self, *args, **kwargs):
674 self.name = "gift_cards"
675 self.model = GiftCards
676 self.model_name = "giftCards"
677 self.columns = gift_cards_columns
679 sort_map = {
680 GiftCards.balance: "BALANCE",
681 GiftCards.createdAt: "CREATED_AT",
682 GiftCards.deactivatedAt: "DISABLED_AT",
683 GiftCards.expiresOn: "EXPIRES_ON",
684 GiftCards.id: "ID",
685 GiftCards.initialValue: "INITIAL_VALUE",
686 GiftCards.updatedAt: "UPDATED_AT",
687 }
688 self.sort_map = {key.name.lower(): value for key, value in sort_map.items()}
690 self.conditions_op_map = {
691 ("createdat", FilterOperator.GREATER_THAN): "created_at:>",
692 ("createdat", FilterOperator.GREATER_THAN_OR_EQUAL): "created_at:>=",
693 ("createdat", FilterOperator.LESS_THAN): "created_at:<",
694 ("createdat", FilterOperator.LESS_THAN_OR_EQUAL): "created_at:<=",
695 ("createdat", FilterOperator.EQUAL): "created_at:",
696 ("expireson", FilterOperator.GREATER_THAN): "expires_on:>",
697 ("expireson", FilterOperator.GREATER_THAN_OR_EQUAL): "expires_on:>=",
698 ("expireson", FilterOperator.LESS_THAN): "expires_on:<",
699 ("expireson", FilterOperator.LESS_THAN_OR_EQUAL): "expires_on:<=",
700 ("expireson", FilterOperator.EQUAL): "expires_on:",
701 ("id", FilterOperator.GREATER_THAN): "id:>",
702 ("id", FilterOperator.GREATER_THAN_OR_EQUAL): "id:>=",
703 ("id", FilterOperator.LESS_THAN): "id:<",
704 ("id", FilterOperator.LESS_THAN_OR_EQUAL): "id:<=",
705 ("id", FilterOperator.EQUAL): "id:",
706 }
707 super().__init__(*args, **kwargs)
709 def meta_get_tables(self, *args, **kwargs) -> dict:
710 response = self.query_graphql("""{
711 giftCardsCount(limit:null) {
712 count
713 } }""")
714 row_count = response["data"]["giftCardsCount"]["count"]
716 return {
717 "table_name": self.name,
718 "table_type": "BASE TABLE",
719 "table_description": "List of gift cards.",
720 "row_count": row_count,
721 }
723 def meta_get_primary_keys(self, table_name: str) -> List[Dict]:
724 return [
725 {
726 "table_name": table_name,
727 "column_name": "id",
728 }
729 ]
731 def meta_get_foreign_keys(self, table_name: str, all_tables: List[str]) -> List[Dict]:
732 return [
733 {
734 "PARENT_TABLE_NAME": table_name,
735 "PARENT_COLUMN_NAME": "customerId",
736 "CHILD_TABLE_NAME": "customers",
737 "CHILD_COLUMN_NAME": "id",
738 },
739 {
740 "PARENT_TABLE_NAME": table_name,
741 "PARENT_COLUMN_NAME": "orderId",
742 "CHILD_TABLE_NAME": "orders",
743 "CHILD_COLUMN_NAME": "id",
744 },
745 ]