Cancel and close unpaid orders after two days, with Mechanic.

Mechanic is an automation development platform for Shopify. :)

Cancel and close unpaid orders after two days

by Isaac Bowen (team@usemechanic.com)

Clear the clutter in your orders list, automatically! On a nightly basis or on-demand, this task scans for orders that are more than two days old (customizable!), and cancels and closes the order if its financial status is still marked "pending".

Runs every day at midnight and when a user triggers the task. Configuration includes days to wait before checking order, attempt to void payment, restock inventory, send cancellation email to customer, and tag to add to the order.

15-day free trial – unlimited tasks

Documentation

This task scans for orders that are more than two days old (customizable!) that have a financial status of "pending", and ensures that they are all closed and cancelled. Orders that are already closed will be cancelled, and orders that are already cancelled will be closed. Optionally, choose to add a tag to such orders, and Mechanic will ensure that all qualifying orders receive your chosen tag.

This task runs every night at midnight (in your store's local time). Run this task manually to perform the scan on demand.

Tip: To easily see which orders this task has cancelled, fill in the "Tag to add to the order" option.

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Gurus, 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.

Events
every day at midnight (mechanic/scheduler/daily)
when a user triggers the task (mechanic/user/trigger)
Options
days to wait before checking order (number, required), attempt to void payment (boolean), restock inventory (boolean), send cancellation email to customer (boolean), tag to add to the order
Script
{% assign orders = shop.orders.any.pending %}

{% if event.preview %}
  {% assign orders = '[{"id": 1234567890, "admin_graphql_api_id": "gid://shopify/Order/1234567890", "processed_at": "1990-01-01"}]' | parse_json %}
{% else %}
  {% assign orders = shop.orders.any.pending %}
{% endif %}

{% assign interval_s = 60 | times: 60 | times: 24 | times: options.days_to_wait_before_checking_order__number_required %}
{% assign maximum_date_s = "now" | date: "%s" | minus: interval_s %}

{% for order in orders %}
  {% assign processed_at_s = order.processed_at | default: order.created_at | date: "%s" | times: 1 %}

  {% if processed_at_s > maximum_date_s %}
    {% continue %}
  {% endif %}

  {% if order.cancelled_at == blank %}
    {% action "shopify" %}
      [
        "post",
        "/admin/orders/{{ order.id }}/cancel.json",
        {
          {% if options.attempt_to_void_payment__boolean %}
            "refund": {
              "note": {{ task.name | json }},
              "transactions": [
                {
                  "parent_id": {{ order.transactions.first.id | json }},
                  "amount": "0.0",
                  "kind": "void",
                  "gateway": {{ order.transactions.first.gateway | json }}
                }
              ]
            },
          {% endif %}
          "restock": {{ options.restock_inventory__boolean | json }},
          "email": {{ options.send_cancellation_email_to_customer__boolean | json }}
        }
      ]
    {% endaction %}
  {% endif %}

  {% assign do_tagging = false %}
  {% if options.tag_to_add_to_the_order != blank %}
    {% assign order_tags = order.tags | downcase | split: ", " %}
    {% assign order_tag_to_match = options.tag_to_add_to_the_order | downcase | strip %}
    {% unless order_tags contains order_tag_to_match %}
      {% assign do_tagging = true %}
    {% endunless %}
  {% endif %}

  {% if order.closed_at == blank or do_tagging %}
    {% action "shopify" %}
      mutation {
        {% if order.closed_at == blank %}
          orderClose(
            input: {
              id: {{ order.admin_graphql_api_id | json }}
            }
          ) {
            order {
              closed
              closedAt
            }
            userErrors {
              field
              message
            }
          }
        {% endif %}


        {% if do_tagging %}
          tagsAdd(
            id: {{ order.admin_graphql_api_id | json }}
            tags: {{ options.tag_to_add_to_the_order | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        {% endif %}
      }
    {% endaction %}
  {% endif %}
{% endfor %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.
Defaults
Days to wait before checking order
2