module Spree class ShippingMethod < Spree::Base acts_as_paranoid include Spree::CalculatedAdjustments include Spree::Metadata if defined?(Spree::Webhooks::HasWebhooks) include Spree::Webhooks::HasWebhooks end if defined?(Spree::VendorConcern) include Spree::VendorConcern end DISPLAY = [:both, :front_end, :back_end] # Used for #refresh_rates DISPLAY_ON_FRONT_END = 1 DISPLAY_ON_BACK_END = 2 default_scope { where(deleted_at: nil) } has_many :shipping_method_categories, dependent: :destroy has_many :shipping_categories, through: :shipping_method_categories has_many :shipping_rates, inverse_of: :shipping_method has_many :shipments, through: :shipping_rates has_many :shipping_method_zones, class_name: 'Spree::ShippingMethodZone', foreign_key: 'shipping_method_id' has_many :zones, through: :shipping_method_zones, class_name: 'Spree::Zone' belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory', optional: true validates :name, :display_on, presence: true validate :at_least_one_shipping_category def include?(address) return false unless address zones.includes(:zone_members).any? do |zone| zone.include?(address) end end def build_tracking_url(tracking) return if tracking.blank? || tracking_url.blank? tracking_url.gsub(/:tracking/, ERB::Util.url_encode(tracking)) # :url_encode exists in 1.8.7 through 2.1.0 end def self.calculators spree_calculators.send(model_name_without_spree_namespace). select { |c| c.to_s.constantize < Spree::ShippingCalculator } end def available_to_display?(display_filter) (frontend? && display_filter == DISPLAY_ON_FRONT_END) || (backend? && display_filter == DISPLAY_ON_BACK_END) end private # Some shipping methods are only meant to be set via backend def frontend? display_on.in?(['both', 'front_end']) end def backend? display_on.in?(['both', 'back_end']) end def at_least_one_shipping_category if shipping_categories.empty? errors.add(:base, :required_shipping_category) end end end end