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