Skip to content

Commit

Permalink
first batch of REST to GraphQL conversions for products and variants
Browse files Browse the repository at this point in the history
  • Loading branch information
tekhaus committed Sep 1, 2024
1 parent a47e252 commit 6bd3b78
Show file tree
Hide file tree
Showing 13 changed files with 609 additions and 223 deletions.
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,6 @@ This directory is built automatically. Each task's documentation is generated fr
* [Email vendors when their products are ordered](./email-vendors-when-their-products-are-ordered)
* [Email your customers after a quiet period of no orders](./email-your-customers-after-a-quiet-period-of-no-orders)
* [Forward incoming email to another address](./forward-incoming-email-to-another-address)
* [Generate a simple product catalog PDF](./generate-a-simple-product-catalog-pdf)
* [Get email alerts for FBA failures](./get-email-alerts-for-fba-failures)
* [Get email alerts for out of stock products](./get-email-alerts-for-out-of-stock-products)
* [Notify a team when a tagged product is ordered](./notify-a-team-when-a-tagged-product-is-ordered)
Expand Down Expand Up @@ -1402,6 +1401,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Find duplicate SKUs](./find-duplicate-skus)
* [Generate a discount code when a certain product is purchased](./generate-a-discount-code-when-a-certain-product-is-purchased)
* [Generate a product discount when a voucher product is purchased](./generate-a-product-discount-when-a-voucher-product-is-purchased)
* [Generate a simple product catalog PDF](./generate-a-simple-product-catalog-pdf)
* [Hide out-of-stock products](./hide-out-of-stock-products)
* [Keep inventory levels in sync within products](./keep-inventory-levels-in-sync-within-products)
* [Maintain a collection of new products](./maintain-a-collection-of-new-products)
Expand Down Expand Up @@ -1556,6 +1556,7 @@ This directory is built automatically. Each task's documentation is generated fr
### Sale

* [Advanced: Scheduled Price Changes](./advanced-scheduled-price-changes)
* [Auto-tag products that have a "compare at" price](./auto-tag-products-that-have-a-compare-at-price)

### Sales Channel

Expand Down
3 changes: 2 additions & 1 deletion docs/auto-tag-orders-using-product-tags/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Use this task to tag incoming orders with all the product tags in the order. Opt
```json
{
"only_copy_these_tags__array": null,
"only_copy_tags_having_this_prefix": null
"only_copy_tags_having_one_of_these_prefixes__array": null
}
```

Expand All @@ -25,6 +25,7 @@ Use this task to tag incoming orders with all the product tags in the order. Opt
shopify/orders/create
mechanic/user/trigger
mechanic/shopify/bulk_operation
mechanic/user/order
```

[Learn about event subscriptions in Mechanic](https://learn.mechanic.dev/core/tasks/subscriptions)
Expand Down
171 changes: 123 additions & 48 deletions docs/auto-tag-orders-using-product-tags/script.liquid
Original file line number Diff line number Diff line change
@@ -1,35 +1,95 @@
{% assign only_copy_these_tags = options.only_copy_these_tags__array %}
{% assign only_copy_tags_having_one_of_these_prefixes = options.only_copy_tags_having_one_of_these_prefixes__array %}

{% comment %}
-- check configured tags to make sure no inadvertent spaces are present
{% endcomment %}

{% for tag in only_copy_these_tags %}
{% assign tag_check = tag | strip %}

{% if tag_check == "" %}
{% error "'Only copy these tags' contains an empty entry. Please correct to continue." %}
{% endif %}
{% endfor %}

{% for tag in only_copy_tags_having_one_of_these_prefixes %}
{% assign tag_check = tag | strip %}

{% if tag_check == "" %}
{% error "'Only copy tags having one of these prefixes' contains an empty entry. Please correct to continue." %}
{% endif %}
{% endfor %}

{% assign order_ids_tags_and_product_tags = array %}

{% if event.topic == "shopify/orders/create" %}
{% if event.topic == "shopify/orders/create" or event.topic == "mechanic/user/order" %}
{% comment %}
-- query the order, line items, products, and tags
{% endcomment %}

{% capture query %}
query {
order(id: {{ order.admin_graphql_api_id | json }}) {
id
tags
lineItems(first: 250) {
nodes {
product {
tags
}
}
}
}
}
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
{% capture order_json %}
{% capture result_json %}
{
"admin_graphql_api_id": "gid://shopify/Order/12345",
"line_items": [
{
"product": {
"tags": {{ options.only_copy_these_tags__array | join: ", " | default: "preorder" | json }}
}
},
{
"product": {
"tags": {{ options.only_copy_tags_having_this_prefix | default: "important" | append: "-order" | json }}
"data": {
"order": {
"id": "gid://shopify/Order/1234567890",
"lineItems": {
"nodes": [
{
"product": {
"tags": [
"preview-tag",
{{ only_copy_these_tags.first | json }},
{{ only_copy_tags_having_one_of_these_prefixes.first | json }}
]
}
}
]
}
}
]
}
}
{% endcapture %}

{% assign order = order_json | parse_json %}
{% assign result = result_json | parse_json %}
{% endif %}

{% assign order_product_tags = order.line_items | map: "product" | map: "tags" | join: ", " | split: ", " %}
{% assign order = result.data.order %}

{% comment %}
-- save order ID and tags as the only item in the array for processing
{% endcomment %}

{% assign item = array %}
{% assign item[0] = order.admin_graphql_api_id %}
{% assign item[1] = order.tags | split: ", " %}
{% assign item[2] = order_product_tags %}
{% assign item[0] = order.id %}
{% assign item[1] = order.tags %}
{% assign item[2] = order.lineItems.nodes | map: "product" | map: "tags" | uniq %}
{% assign order_ids_tags_and_product_tags[0] = item %}

{% elsif event.topic == "mechanic/user/trigger" %}
{% comment %}
-- use bulk op to get all orders in the shop
{% endcomment %}

{% capture bulk_operation_query %}
query {
orders {
Expand All @@ -42,7 +102,6 @@
edges {
node {
__typename
id
product {
tags
}
Expand Down Expand Up @@ -71,27 +130,33 @@
}
}
{% endaction %}

{% elsif event.topic == "mechanic/shopify/bulk_operation" %}
{% if event.preview %}
{% capture objects_jsonl %}
{"__typename":"Order","id":"gid:\/\/shopify\/Order\/1234567890","tags":[]}
{"__typename":"LineItem","__parentId":"gid:\/\/shopify\/Order\/1234567890","id":"gid:\/\/shopify\/LineItem\/1234567890","product":{"tags":{{ options.only_copy_these_tags__array | join: "," | default: "preorder" | split: "," | json }}},"__parentId":"gid:\/\/shopify\/Order\/1234567890"}
{"__typename":"LineItem","__parentId":"gid:\/\/shopify\/Order\/1234567890","id":"gid:\/\/shopify\/LineItem\/2345678901","product":{"tags":[{{ options.only_copy_tags_having_this_prefix | default: "important" | append: "-order" | json }}]},"__parentId":"gid:\/\/shopify\/Order\/1234567890"}
{"__typename":"LineItem","__parentId":"gid:\/\/shopify\/Order\/1234567890","product":{"tags":["preview-tag",{{ only_copy_these_tags.first | json }},{{ only_copy_tags_having_one_of_these_prefixes.first | json }}]}}
{% endcapture %}

{% assign bulkOperation = hash %}
{% assign bulkOperation["objects"] = objects_jsonl | parse_jsonl %}
{% endif %}

{% assign orders = bulkOperation.objects | where: "__typename", "Order" %}
{% assign lineItems = bulkOperation.objects | where: "__typename", "LineItem" %}
{% assign line_items = bulkOperation.objects | where: "__typename", "LineItem" %}

{% comment %}
-- save order IDs and tags in array for processing
{% endcomment %}

{% for order in orders %}
{% assign order_products = lineItems | where: "__parentId", order.id | map: "product" | compact %}
{% assign order_product_tags = array %}
{% for product in order_products %}
{% assign order_product_tags = order_product_tags | concat: product.tags | uniq %}
{% endfor %}
{% assign order_product_tags
= line_items
| where: "__parentId", order.id
| map: "product"
| map: "tags"
| uniq
%}

{% assign item = array %}
{% assign item[0] = order.id %}
Expand All @@ -101,44 +166,54 @@
{% endfor %}
{% endif %}

{% comment %}
-- process items to see which tags to add to each order
{% endcomment %}

{% for item in order_ids_tags_and_product_tags %}
{% assign order_id = item[0] %}
{% assign order_tags = item[1] %}
{% assign order_product_tags = item[2] %}

{% assign tags_to_add = array %}

{% for tag in order_product_tags %}
{% if order_tags contains tag %}
{% for product_tag in order_product_tags %}
{% if order_tags contains product_tag %}
{% continue %}
{% endif %}

{% if options.only_copy_these_tags__array != blank %}
{% if options.only_copy_these_tags__array contains nil %}
{% error "'Only copy these tags' must not contain any blank items. If you don't want to use this option, remove its remaining items." %}
{% endif %}

{% unless options.only_copy_these_tags__array contains tag %}
{% continue %}
{% endunless %}
{% if only_copy_these_tags == blank and only_copy_tags_having_one_of_these_prefixes == blank %}
{% assign tags_to_add = tags_to_add | push: product_tag %}
{% continue %}
{% endif %}

{% if options.only_copy_tags_having_this_prefix != blank %}
{% assign prefix_length = options.only_copy_tags_having_this_prefix.size %}
{% assign tag_substr = tag | slice: 0, prefix_length %}
{% if tag_substr != options.only_copy_tags_having_this_prefix %}
{% continue %}
{% for tag in only_copy_these_tags %}
{% if tag == product_tag %}
{% assign tags_to_add = tags_to_add | push: product_tag %}
{% endif %}
{% endif %}
{% endfor %}

{% comment %}
-- make sure the prefix matches the beginning of the tag
{% endcomment %}

{% assign tags_to_add[tags_to_add.size] = tag %}
{% for tag in only_copy_tags_having_one_of_these_prefixes %}
{% assign prefix_length = tag.size %}
{% assign product_tag_substr = product_tag | slice: 0, prefix_length %}

{% if tag == product_tag_substr %}
{% assign tags_to_add = tags_to_add | push: product_tag %}
{% endif %}
{% endfor %}
{% endfor %}

{% if event.preview and tags_to_add == empty %}
{% error "It looks like you have conflicting options configured. Please double-check your options, and try again. :)" %}
{% endif %}
{% comment %}
-- remove duplicate tags before adding to order
{% endcomment %}

{% assign tags_to_add = tags_to_add | compact | uniq %}

{% if tags_to_add != empty %}
{% if tags_to_add != blank %}
{% action "shopify" %}
mutation {
tagsAdd(
Expand Down
10 changes: 4 additions & 6 deletions docs/auto-tag-products-that-have-a-compare-at-price/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Auto-tag products that have a "compare at" price

Tags: Auto-Tag, Compare at, Products
Tags: Auto-Tag, Compare at, Products, Sale

This task will keep your sale tags in sync, without any manual work. Configure the task with a tag to apply (and optionally a tag for products that aren't on sale), and Mechanic will take care of applying and removing tags as appropriate. If you're using Shopify discounts, this can allow you to use automatic sale collections – based on these tags – to control eligibility for your discounts.
This task will keep your sale tags in sync, without any manual work. Configure the task with a tag to apply (and optionally a tag for products that _aren't_ on sale), and Mechanic will take care of applying and removing tags as appropriate.

* View in the task library: [tasks.mechanic.dev/auto-tag-products-that-have-a-compare-at-price](https://tasks.mechanic.dev/auto-tag-products-that-have-a-compare-at-price)
* Task JSON, for direct import: [task.json](../../tasks/auto-tag-products-that-have-a-compare-at-price.json)
Expand All @@ -12,7 +12,7 @@ This task will keep your sale tags in sync, without any manual work. Configure t

```json
{
"tag_for_sale_products": "on-sale",
"tag_for_sale_products__required": "on-sale",
"tag_for_all_other_products": "not-on-sale",
"sale_products_must_have_a_price_lower_than_the_compare_at_price__boolean": true
}
Expand All @@ -32,10 +32,8 @@ mechanic/user/trigger

## Documentation

This task will keep your sale tags in sync, without any manual work. Configure the task with a tag to apply (and optionally a tag for products that aren't on sale), and Mechanic will take care of applying and removing tags as appropriate. If you're using Shopify discounts, this can allow you to use automatic sale collections – based on these tags – to control eligibility for your discounts.
This task will keep your sale tags in sync, without any manual work. Configure the task with a tag to apply (and optionally a tag for products that _aren't_ on sale), and Mechanic will take care of applying and removing tags as appropriate.

This task will keep your sale tags in sync, without any manual work. Configure the task with a tag to apply (and optionally a tag for products that _aren't_ on sale), and Mechanic will take care of applying and removing tags as appropriate.

Run this task manually to update your entire product catalog at once.

## Installing this task
Expand Down
Loading

0 comments on commit 6bd3b78

Please sign in to comment.