Hi
I am wanting to change the shipping rate name/message depending on variant metafields. Is it possible to use variant matafields as a condition, and if so can anyone point me in the direction of an example code?
Hi
I am wanting to change the shipping rate name/message depending on variant metafields. Is it possible to use variant matafields as a condition, and if so can anyone point me in the direction of an example code?
Hi @kathryn7 , I’ve generated the following script for you. This example looks for a shipping rate called “This is the old name” and renames it to “This is the new name” when there is a cart item which has the line item property of “special_property” set to “yes”.
########################################################################
## Create Shopify scripts without writing code at playwrightapp.com ##
########################################################################
class Campaign
def initialize(condition, *qualifiers)
@condition = (condition.to_s + '?').to_sym
@qualifiers = PostCartAmountQualifier ? [] : [] rescue qualifiers.compact
@line_item_selector = qualifiers.last unless @line_item_selector
qualifiers.compact.each do |qualifier|
is_multi_select = qualifier.instance_variable_get(:@conditions).is_a?(Array)
if is_multi_select
qualifier.instance_variable_get(:@conditions).each do |nested_q|
@post_amount_qualifier = nested_q if nested_q.is_a?(PostCartAmountQualifier)
@qualifiers << qualifier
end
else
@post_amount_qualifier = qualifier if qualifier.is_a?(PostCartAmountQualifier)
@qualifiers << qualifier
end
end if @qualifiers.empty?
end
def qualifies?(cart)
return true if @qualifiers.empty?
@unmodified_line_items = cart.line_items.map do |item|
new_item = item.dup
new_item.instance_variables.each do |var|
val = item.instance_variable_get(var)
new_item.instance_variable_set(var, val.dup) if val.respond_to?(:dup)
end
new_item
end if @post_amount_qualifier
@qualifiers.send(@condition) do |qualifier|
is_selector = false
if qualifier.is_a?(Selector) || qualifier.instance_variable_get(:@conditions).any? { |q| q.is_a?(Selector) }
is_selector = true
end rescue nil
if is_selector
raise "Missing line item match type" if @li_match_type.nil?
cart.line_items.send(@li_match_type) { |item| qualifier.match?(item) }
else
qualifier.match?(cart, @line_item_selector)
end
end
end
def run_with_hooks(cart)
before_run(cart) if respond_to?(:before_run)
run(cart)
after_run(cart)
end
def after_run(cart)
@discount.apply_final_discount if @discount && @discount.respond_to?(:apply_final_discount)
revert_changes(cart) unless @post_amount_qualifier.nil? || @post_amount_qualifier.match?(cart)
end
def revert_changes(cart)
cart.instance_variable_set(:@line_items, @unmodified_line_items)
end
end
class ChangeRateName < Campaign
def initialize(condition, customer_qualifier, cart_qualifier, li_match_type, line_item_qualifier, rate_selector, new_name)
super(condition, customer_qualifier, cart_qualifier, line_item_qualifier)
@li_match_type = (li_match_type.to_s + '?').to_sym
@rate_selector = rate_selector
@new_name = new_name
end
def run(rates, cart)
return unless qualifies?(cart) && @rate_selector
rates.each do|rate|
rate.change_name(@new_name, {message: ""}) if @rate_selector.match?(rate)
end
end
end
class Selector
def partial_match(match_type, item_info, possible_matches)
match_type = (match_type.to_s + '?').to_sym
if item_info.kind_of?(Array)
possible_matches.any? do |possibility|
item_info.any? do |search|
search.send(match_type, possibility)
end
end
else
possible_matches.any? do |possibility|
item_info.send(match_type, possibility)
end
end
end
end
class LineItemPropertiesSelector < Selector
def initialize(target_properties)
@target_properties = target_properties
end
def match?(line_item)
line_item_props = line_item.properties
@target_properties.all? do |key, value|
next unless line_item_props.has_key?(key)
true if line_item_props[key].downcase == value.downcase
end
end
end
class RateNameSelector < Selector
def initialize(match_type, match_condition, names)
@match_condition = match_condition
@invert = match_type == :does_not
@names = names.map(&:downcase)
end
def match?(shipping_rate)
name = shipping_rate.name.downcase
case @match_condition
when :match
return @invert ^ @names.include?(name)
else
return @invert ^ partial_match(@match_condition, name, @names)
end
end
end
CAMPAIGNS = [
ChangeRateName.new(
:all,
nil,
nil,
:any,
LineItemPropertiesSelector.new(
{"special_property" => "yes"}
),
RateNameSelector.new(
:does,
:match,
["This is the old name"]
),
"This is the new name"
)
].freeze
CAMPAIGNS.each do |campaign|
campaign.run(Input.shipping_rates, Input.cart)
end
Output.shipping_rates = Input.shipping_rates
Here is a screenshot of the UI so you can get a sense for how to customize the values at the bottom of the script:
Let me know if that is helpful for you,
Matthew
Thank you