BGL has three logical operators for combining conditions: and, or, and not. They behave the way they read in English.
when
order.subtotal > 100.0
and order.shipping_address.country is "US"
then
...
end
Both conditions must be true for the rule to fire.
The three operators
| Operator | Meaning |
|---|---|
and |
Both sides must be true. |
or |
At least one side must be true. |
not |
Flips true to false and false to true. |
order_line.gift_wrap and order_line.custom.is_restricted
order.status is "pending" or order.status is "processing"
not order_line.custom.is_backorder
Precedence: which goes first
When you mix operators, BGL evaluates them in this order:
-
not(highest — applies to whatever’s right next to it) and-
or(lowest)
So A or B and C means A or (B and C), not (A or B) and C.
When in doubt, use parentheses. They cost nothing and make intent obvious.
# Without parentheses — relies on precedence
when
order.custom.is_gift or order.subtotal > 100 and order.shipping_address.country is "US"
then
...
end
# Same condition, parentheses make it unambiguous
when
order.custom.is_gift or (order.subtotal > 100 and order.shipping_address.country is "US")
then
...
end
Real-world combinations
At least one of two countries:
when
order.shipping_address.country is "US"
or order.shipping_address.country is "CA"
then
...
end
All three must be true:
when
order.subtotal > 500.0
and order.shipping_address.country is "US"
and not order.custom.is_gift
then
...
end
Two groups, either group qualifies:
when
(order.subtotal > 1000.0 and order.custom.priority is "high")
or order.custom.customer_tier is "vip"
then
...
end
When to split into multiple when blocks
You don’t have to cram everything into one condition. Often it reads better to split:
# One block, complex condition
when
(order.subtotal > 500.0 or order.custom.is_priority)
and order.shipping_address.country is "US"
then
set order.custom.tag to "premium-us"
set order.custom.region to "us-premium"
end
# Two blocks, simpler each
when
order.subtotal > 500.0 or order.custom.is_priority
then
set order.custom.tag to "premium"
end
when
order.custom.tag is "premium" and order.shipping_address.country is "US"
then
set order.custom.region to "us-premium"
end
The two-block version uses the fact that the first when can set up state that the second checks. (See Variables for an alternative using $variables instead of model fields.)
Tips
-
Indent each
and/oron its own line. Long conditions become unreadable on one line. Put the operator at the start of the line so the structure is obvious at a glance. -
andchains can be reordered for performance. BGL stops evaluating anandas soon as one side is false. Cheaper checks first means faster rules. -
notis usually clearer than the negative form of an operator.not order_line.gift_wrapreads better than checkingorder_line.gift_wrap = false.
Comments
Please sign in to leave a comment.