diff --git a/backend/app/views/spree/admin/promotions/rules/_store.html.erb b/backend/app/views/spree/admin/promotions/rules/_store.html.erb new file mode 100644 index 00000000000..cce8ac2e37f --- /dev/null +++ b/backend/app/views/spree/admin/promotions/rules/_store.html.erb @@ -0,0 +1,6 @@ +
+ + <%= select_tag "#{param_prefix}[store_ids][]", + options_from_collection_for_select(Spree::Store.all, :id, :name, promotion_rule.store_ids), + multiple: true, class: "select2 fullwidth" %> +
diff --git a/core/app/models/spree/promotion/rules/store.rb b/core/app/models/spree/promotion/rules/store.rb new file mode 100644 index 00000000000..276a77e9b09 --- /dev/null +++ b/core/app/models/spree/promotion/rules/store.rb @@ -0,0 +1,20 @@ +module Spree + class Promotion + module Rules + class Store < PromotionRule + has_many :promotion_rule_stores, class_name: "Spree::PromotionRuleStore", + foreign_key: :promotion_rule_id, + dependent: :destroy + has_many :stores, through: :promotion_rule_stores, class_name: "Spree::Store" + + def applicable?(promotable) + promotable.is_a?(Spree::Order) + end + + def eligible?(order, _options = {}) + stores.none? || stores.include?(order.store) + end + end + end + end +end diff --git a/core/app/models/spree/promotion_rule_store.rb b/core/app/models/spree/promotion_rule_store.rb new file mode 100644 index 00000000000..7a97f008f86 --- /dev/null +++ b/core/app/models/spree/promotion_rule_store.rb @@ -0,0 +1,8 @@ +module Spree + class PromotionRuleStore < Spree::Base + self.table_name = "spree_promotion_rules_stores" + + belongs_to :promotion_rule, class_name: "Spree::PromotionRule" + belongs_to :store, class_name: "Spree::Store" + end +end diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml index bf5dacb9baa..400c13d10ec 100644 --- a/core/config/locales/en.yml +++ b/core/config/locales/en.yml @@ -224,6 +224,8 @@ en: form_text: "Apply this promotion to users whose last order was more than X days ago: " spree/promotion/rules/user_role: description: Order includes User with specified Role(s) + spree/promotion/rules/store: + description: Available only to the specified stores spree/promotion_category: name: Name spree/property: @@ -1966,6 +1968,8 @@ en: user_has_no_store_credits: "User does not have any available store credit" store_credit_category: default: Default + store_rule: + choose_stores: Choose Stores street_address: Street Address street_address_2: Street Address (cont'd) subtotal: Subtotal diff --git a/core/db/migrate/20180202190713_create_promotion_rule_stores.rb b/core/db/migrate/20180202190713_create_promotion_rule_stores.rb new file mode 100644 index 00000000000..18546637020 --- /dev/null +++ b/core/db/migrate/20180202190713_create_promotion_rule_stores.rb @@ -0,0 +1,10 @@ +class CreatePromotionRuleStores < ActiveRecord::Migration[5.1] + def change + create_table :spree_promotion_rules_stores do |t| + t.references :store, foreign_key: { to_table: "spree_stores" } + t.references :promotion_rule, foreign_key: { to_table: "spree_promotion_rules" } + + t.timestamps + end + end +end diff --git a/core/lib/spree/app_configuration.rb b/core/lib/spree/app_configuration.rb index fdfa36511ad..7e0e8df44d0 100644 --- a/core/lib/spree/app_configuration.rb +++ b/core/lib/spree/app_configuration.rb @@ -444,6 +444,7 @@ def environment Spree::Promotion::Rules::OptionValue Spree::Promotion::Rules::FirstRepeatPurchaseSince Spree::Promotion::Rules::UserRole + Spree::Promotion::Rules::Store ] promos.actions = %w[ diff --git a/core/spec/models/spree/promotion/rules/store_spec.rb b/core/spec/models/spree/promotion/rules/store_spec.rb new file mode 100644 index 00000000000..9bc89ecc4fe --- /dev/null +++ b/core/spec/models/spree/promotion/rules/store_spec.rb @@ -0,0 +1,33 @@ +require "rails_helper" + +RSpec.describe Spree::Promotion::Rules::Store, type: :model do + let(:rule) { described_class.new } + + context "#eligible?(order)" do + let(:order) { Spree::Order.new } + + it "is eligible if no stores are provided" do + expect(rule).to be_eligible(order) + end + + it "is eligible if stores include the order's store" do + default_store = Spree::Store.new(name: "Default") + other_store = Spree::Store.new(name: "Other") + + rule.stores = [default_store, other_store] + order.store = default_store + + expect(rule).to be_eligible(order) + end + + it "is not eligible if order is placed in a different store" do + default_store = Spree::Store.new(name: "Default") + other_store = Spree::Store.new(name: "Other") + + rule.stores = [other_store] + order.store = default_store + + expect(rule).not_to be_eligible(order) + end + end +end