Mechanic is a development and ecommerce automation platform for Shopify. :)
This task resets your inventory levels at the default location in your shop, every night, for all products within a given collection (configured by ID).
Runs Occurs every day at midnight (in local time). Configuration includes inventory level to apply and collection id.
Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Shopifolks, everybody.
That’s why we make it easy to configure automation without code, why we make it easy to tweak the underlying code once tasks are installed, and why we publish it all here for everyone to learn from.
(By the way, have you seen our documentation? Have you joined the Slack community?)
mechanic/scheduler/daily
{% assign inventory_level_to_apply = options.inventory_level_to_apply__number_required %} {% assign collection_id = options.collection_id__number_required %} {% assign location_id = shop.primary_location_id | prepend: "gid://shopify/Location/" %} {% comment %} -- get all product IDs from the configured collection {% endcomment %} {% assign cursor = nil %} {% assign product_ids = array %} {% for n in (1..100) %} {% capture query %} query { collection(id: {{ collection_id | prepend: "gid://shopify/Collection/" | json }}) { products( first: 250 after: {{ cursor | json }} ) { pageInfo { hasNextPage endCursor } nodes { id } } } } {% endcapture %} {% assign result = query | shopify %} {% if event.preview %} {% capture result_json %} { "data": { "collection": { "products": { "nodes": [ { "id": "gid://shopify/Product/1234567890" } ] } } } } {% endcapture %} {% assign result = result_json | parse_json %} {% endif %} {% assign collection = result.data.collection %} {% assign product_ids = collection.products.nodes | map: "id" | concat: product_ids %} {% if result.data.collection.products.pageInfo.hasNextPage %} {% assign cursor = result.data.collection.products.pageInfo.endCursor %} {% else %} {% break %} {% endif %} {% endfor %} {% comment %} -- make sure collection exists and has products {% endcomment %} {% if collection == blank %} {% log "Collection not found by ID." %} {% break %} {% elsif product_ids == blank %} {% log "No products found in the collection." %} {% break %} {% endif %} {% comment %} -- determine which inventory levels need to be set on this task run {% endcomment %} {% assign inventory_inputs = array %} {% for product_id in product_ids %} {% comment %} -- get all variants for this product (up to 2K), and their inventory items and inventory levels at the default location {% endcomment %} {% assign cursor = nil %} {% assign variants = array %} {% for n in (1..8) %} {% capture query %} query { product(id: {{ product_id | json }}) { id handle variants( first: 250 after: {{ cursor | json }} ) { pageInfo { hasNextPage endCursor } nodes { inventoryItem { id tracked inventoryLevel(locationId: {{ location_id | json }}) { quantities(names: "available") { quantity } } } } } } } {% endcapture %} {% assign result = query | shopify %} {% if event.preview %} {% capture result_json %} { "data": { "product": { "variants": { "nodes": [ { "inventoryItem": { "id": "gid://shopify/InventoryItem/1234567890", "tracked": "true", "inventoryLevel": { "quantities": { "quantity": {{ inventory_level_to_apply | minus: 1 }} } } } } ] } } } } {% endcapture %} {% assign result = result_json | parse_json %} {% endif %} {% comment %} -- if a variant's inventory is tracked (i.e. managed by Shopify) and the available quantity at the default location differs from the configured level, then add it to input array {% endcomment %} {% for variant in result.data.product.variants.nodes %} {% if variant.inventoryItem.tracked and variant.inventoryItem.inventoryLevel.quantities.first.quantity != inventory_level_to_apply %} {% assign inventory_input = hash %} {% assign inventory_input["inventoryItemId"] = variant.inventoryItem.id %} {% assign inventory_input["locationId"] = location_id %} {% assign inventory_input["quantity"] = inventory_level_to_apply %} {% assign inventory_inputs = inventory_inputs | push: inventory_input %} {% endif %} {% endfor %} {% if result.data.product.variants.pageInfo.hasNextPage %} {% assign cursor = result.data.product.variants.pageInfo.endCursor %} {% else %} {% break %} {% endif %} {% endfor %} {% endfor %} {% if inventory_inputs != blank %} {% assign groups_of_inventory_inputs = inventory_inputs | in_groups_of: 250, fill_with: false %} {% for group_of_inventory_inputs in groups_of_inventory_inputs %} {% action "shopify" %} mutation { inventorySetQuantities( input: { name: "available" reason: "correction" ignoreCompareQuantity: true quantities: {{ group_of_inventory_inputs | graphql_arguments }} } ) { userErrors { code field message } } } {% endaction %} {% endfor %} {% endif %}