Manage fulfillment shipment status using order tags, with Mechanic.

Mechanic is a development and ecommerce automation platform for Shopify. :)

Manage fulfillment shipment status using order tags

Use this task to easily set the shipment status on your fulfilled orders. Just add a tag, and new fulfillment events will be created, using the corresponding shipment status. Optionally, you may have the task attempt to fulfill the order first and may choose whether to send shipment status notifications to the customer.

Runs Occurs whenever an order is updated. Configuration includes shipment tags and status, attempt to fulfill the order before setting shipment status, and send shipment notifications to customer.

15-day free trial – unlimited tasks

Documentation

Use this task to easily set the shipment status on your fulfilled orders. Just add a tag, and new fulfillment events will be created, using the corresponding shipment status. Optionally, you may have the task attempt to fulfill the order first and may choose whether to send shipment status notifications to the customer.

This task comes preconfigured with Shopify's shipment status identifiers on the right, and friendly order tags on the left. Feel free to update the tag names on the left-hand side. Do not modify the labels on the right! These must correspond directly to Shopify fulfillment event statuses.

Notes:
- This task will fulfill all open fulfillment orders from any location, if it has been configured to attempt to fulfill first. This includes digital items (i.e. shipping not required). However, digital items will not have a shipment status set on them.
- When setting the shipment status, the task will use the first shipment tag it finds on the order. Be careful to remove any previous shipment tags before applying a new one, since Shopify auto-updates the order as soon as a tag is applied in admin.
- This task has no knowledge of the typical sequence of shipment progression. It is your responsibility to not inadvertently apply a shipment status tag to an order that has previously been updated to a "later" tag (e.g. setting "CONFIRMED" on an order that was already at "DELIVERED").

Developer details

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?)

Open source
View on GitHub to contribute to this task
Subscriptions
shopify/orders/updated
Tasks use subscriptions to sign up for specific kinds of events. Learn more
Options
shipment tags and status (keyval, required), attempt to fulfill the order before setting shipment status (boolean), send shipment notifications to customer (boolean)
Code
{% assign shipment_tags_and_status = options.shipment_tags_and_status__keyval_required %}
{% assign attempt_to_fulfill_the_order_before_setting_shipment_status = options.attempt_to_fulfill_the_order_before_setting_shipment_status__boolean %}
{% assign send_shipment_notifications_to_customer = options.send_shipment_notifications_to_customer__boolean %}

{% capture query %}
  query {
    order(id: {{ order.admin_graphql_api_id | json }}) {
      id
      name
      tags
      displayFulfillmentStatus
      fulfillments(first: 10) {
        id
        status
        displayStatus
        requiresShipping
        location {
          name
        }
      }
      fulfillmentOrders(
        first: 20
        query: "status:open"
      ) {
        nodes {
          id
          assignedLocation {
            name
          }
          deliveryMethod {
            methodType
          }
        }
      }
    }
  }
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
  {% capture result_json %}
    {
      "data": {
        "order": {
          "id": "gid://shopify/Order/1234567890",
          "name": "#SAMPLE",
          "tags": {{ shipment_tags_and_status.first.first | json }},
          "displayFulfillmentStatus": "FULFILLED",
          "fulfillments": [
            {
              "id": "gid://shopify/Fulfillment/1234567890",
              "status": "SUCCESS",
              "displayStatus": null,
              "requiresShipping": true,
              "location": {
                "name": "Warehouse"
              }
            }
          ],
          "fulfillmentOrders": {
            "nodes": [
              {
                "id": "gid://shopify/FulfillmentOrder/1234567890",
                "assignedLocation": {
                  "name": "Warehouse"
                },
                "deliveryMethod": {
                  "methodType": "SHIPPING"
                }
              }
            ]
          }
        }
      }
    }
  {% endcapture %}

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

{% assign order = result.data.order %}
{% assign fulfillment_orders = order.fulfillmentOrders.nodes %}

{% for order_tag in order.tags %}
  {% if shipment_tags_and_status[order_tag] != blank %}
    {% assign shipment_status_to_set = shipment_tags_and_status[order_tag] %}
    {% break %}
  {% endif %}
{% endfor %}

{% unless shipment_status_to_set %}
  {% log "No shipment status tags found on this order; skipping" %}
  {% break %}
{% endunless %}

{% if attempt_to_fulfill_the_order_before_setting_shipment_status %}
  {% if fulfillment_orders == blank %}
    {% log "This order has no open fulfillment orders to fulfill; proceeding to check/set shipment status." %}

  {% else %}
    {% comment %}
      Note: fulfillments cannot be created with fulfillment orders at different locations or delivery types; so separate them out
    {% endcomment %}

    {% assign fulfillment_order_ids_by_location_and_type = hash %}

    {% for fulfillment_order in fulfillment_orders %}
      {% assign location_and_type
        = fulfillment_order.assignedLocation.name
        | append: "|"
        | append: fulfillment_order.deliveryMethod.methodType
      %}
      {% assign fulfillment_order_ids_by_location_and_type[location_and_type]
        = fulfillment_order_ids_by_location_and_type[location_and_type]
        | default: array
        | push: fulfillment_order.id
      %}
    {% endfor %}

    {% for keyval in fulfillment_order_ids_by_location_and_type %}
      {% action "shopify" %}
        mutation {
          fulfillmentCreateV2(
            fulfillment: {
              lineItemsByFulfillmentOrder: [
                {% for fulfillment_order_id in keyval[1] %}
                  { fulfillmentOrderId: {{ fulfillment_order_id | json }} }
                {% endfor %}
              ]
              notifyCustomer: {{ send_shipment_notifications_to_customer | json }}
            }
          ) {
            fulfillment {
              id
              status
            }
            userErrors {
              field
              message
            }
          }
        }
      {% endaction %}
    {% endfor %}

    {% comment %}
      -- break here so the fulfillments are complete for the next task run on order update
    {% endcomment %}

    {% unless event.preview %}
      {% break %}
    {% endunless %}
  {% endif %}
{% endif %}

{% assign fulfillments
  = order.fulfillments
  | where: "requiresShipping"
  | where: "status", "SUCCESS"
%}

{% if fulfillments == blank %}
  {% log "There are no successful fulfillments that require shipping available to update on this order; skipping." %}
  {% break %}
{% endif %}

{% log
  shipment_status_to_set: shipment_status_to_set,
  fulfillments: fulfillments
%}

{% for fulfillment in fulfillments %}
  {% if fulfillment.displayStatus != shipment_status_to_set %}
    {% action "shopify" %}
      mutation {
        fulfillmentEventCreate(
          fulfillmentEvent: {
            fulfillmentId: {{ fulfillment.id | json }}
            status: {{ shipment_status_to_set }}
          }
        ) {
          fulfillmentEvent {
            id
            status
          }
          userErrors {
            field
            message
          }
        }
      }
    {% endaction %}
  {% endif %}
{% endfor %}
Task code is written in Mechanic Liquid, an extension of open-source Liquid enhanced for automation. Learn more
Defaults
Shipment tags and status
{"shipment_attempted_delivery"=>"ATTEMPTED_DELIVERY", "shipment_confirmed"=>"CONFIRMED", "shipment_delivered"=>"DELIVERED", "shipment_failure"=>"FAILURE", "shipment_in_transit"=>"IN_TRANSIT", "shipment_label_printed"=>"LABEL_PRINTED", "shipment_label_purchased"=>"LABEL_PURCHASED", "shipment_out_for_delivery"=>"OUT_FOR_DELIVERY", "shipment_ready_for_pickup"=>"READY_FOR_PICKUP"}