I’m a Shopify Plus partner working on a fulfillment routing problem for a client and would appreciate a review of our proposed solution before we build it out.
The Problem
Our client sells both refrigerated and standard products for home delivery. They have two boutique fulfillment locations (Saint-Bruno and Sainte-Thérèse). When a customer orders a mix of refrigerated and standard items, Shopify splits the fulfillment: refrigerated items go to the boutique, standard items go to the warehouse.
This split causes the order to land incorrectly in their Odoo ERP and go unprocessed. The intended behavior: when any refrigerated item is in the cart, the entire order must route to one of the two boutiques. If neither boutique can fulfill the full order, checkout should be blocked. Pick-up orders should be unaffected.
Our Proposed Solution
We plan to use the Fulfillment Constraints Function API with a mustFulfillFrom constraint. The function detects a “refrigerated” product tag and forces all cart lines to route to one of the two boutique locations. The FulfillmentConstraintRule will be registered with deliveryMethodTypes: [SHIPPING] to exclude pick-up orders.
run.graphql
query RunInput {
cart {
deliverableLines {
id
merchandise {
__typename
... on ProductVariant {
id
product { hasAnyTag(tags: ["refrigerated"]) }
}
}
}
}
locations(names: ["Saint-Bruno", "Sainte-Thérèse"]) {
id
name
}
}
run.js
// @ts-check
import { no_fulfillment_constraints_result } from '../generated/api';
export function run(input) {
const { deliverableLines } = input.cart;
const { locations } = input;
const hasRefrigeratedItem = deliverableLines.some(
(line) =>
line.merchandise.__typename === 'ProductVariant' &&
line.merchandise.product.hasAnyTag
);
if (!hasRefrigeratedItem) return no_fulfillment_constraints_result();
const allLineIds = deliverableLines.map((line) => line.id);
const validLocationIds = locations.map((loc) => loc.id);
if (validLocationIds.length === 0) return no_fulfillment_constraints_result();
return {
operations: [{
mustFulfillFrom: {
deliverableLineIds: allLineIds,
locationIds: validLocationIds,
}
}]
};
}
Rule registration
mutation {
fulfillmentConstraintRuleCreate(
fulfillmentConstraintRule: {
functionId: "<function-id>"
deliveryMethodTypes: [SHIPPING]
}
) {
fulfillmentConstraintRule { id }
userErrors { field message }
}
}
Questions
-
Untracked inventory - Refrigerated products have inventory tracking disabled in Shopify (dispatched manually via Odoo). When mustFulfillFrom is applied, does Shopify treat untracked inventory as always available at the specified locations, or does it block checkout?
-
Delivery method scoping - Registering with deliveryMethodTypes: [SHIPPING] - does this fully exclude local pick-up orders from the constraint?
-
hasAnyTag on duplicate variant products - Refrigerated products have two variants (online SKU and POS SKU) on the same parent product. If only the online variant is in the cart, will hasAnyTag correctly read the tags from the parent product?
-
Fail-safe behavior - If neither boutique location is returned by the input query (name mismatch or deactivated location), the function returns no_fulfillment_constraints_result(). Does this mean the order routes normally rather than throwing a checkout error?
-
Correct API for this use case - Is the Fulfillment Constraints API the right tool here, or should we be looking at the Order Routing Location Rule API instead?
Any feedback or experience with similar implementations is appreciated.