diff --git a/app/models/solidus_subscriptions/line_item.rb b/app/models/solidus_subscriptions/line_item.rb
index 2583ecc5..efd9d662 100644
--- a/app/models/solidus_subscriptions/line_item.rb
+++ b/app/models/solidus_subscriptions/line_item.rb
@@ -38,5 +38,12 @@ class LineItem < ApplicationRecord
validates :subscribable_id, presence: true
validates :quantity, numericality: { greater_than: 0 }
validates :interval_length, numericality: { greater_than: 0 }, unless: -> { subscription }
+ validate :ensure_subscribable_valid
+
+ def ensure_subscribable_valid
+ return unless subscribable && subscribable.subscribable != true
+
+ errors.add(:subscribable, :cannot_subscribe)
+ end
end
end
diff --git a/app/models/solidus_subscriptions/subscription.rb b/app/models/solidus_subscriptions/subscription.rb
index d261d6e4..62a4db75 100644
--- a/app/models/solidus_subscriptions/subscription.rb
+++ b/app/models/solidus_subscriptions/subscription.rb
@@ -434,12 +434,11 @@ def emit_events_for_update
end
def self.ransackable_attributes(_auth_object = nil)
- %w[actionable_date created_at end_date state updated_at user_id]
+ %w[actionable_date created_at end_date state updated_at user_id]
end
def self.ransackable_associations(_auth_object = nil)
%w[events user]
end
-
end
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index c1c1fce3..f58c203c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -136,3 +136,7 @@ en:
not_active: "cannot pause/resume a subscription which is not active"
state:
cannot_skip: cannot skip a subscription which is canceled or inactive
+ solidus_subscriptions/line_item:
+ attributes:
+ subscribable:
+ cannot_subscribe: "The requested item cannot be subscribed"
diff --git a/db/migrate/20210323165714_update_promotion_rule_names.rb b/db/migrate/20210323165714_update_promotion_rule_names.rb
index f6ee6c23..1adfe1b6 100644
--- a/db/migrate/20210323165714_update_promotion_rule_names.rb
+++ b/db/migrate/20210323165714_update_promotion_rule_names.rb
@@ -5,6 +5,8 @@ class UpdatePromotionRuleNames < ActiveRecord::Migration[5.2]
}.freeze
def change
+ return unless Object.const_defined?("Spree::Promotion")
+
reversible do |dir|
dir.up do
TYPE_RENAMES.each do |old_type, new_type|
diff --git a/lib/generators/solidus_subscriptions/install/install_generator.rb b/lib/generators/solidus_subscriptions/install/install_generator.rb
index e9805d87..2081deab 100644
--- a/lib/generators/solidus_subscriptions/install/install_generator.rb
+++ b/lib/generators/solidus_subscriptions/install/install_generator.rb
@@ -30,6 +30,10 @@ def copy_starter_frontend_files
RUBY
end
+
+ inject_into_file 'app/views/cart_line_items/_product_variants.html.erb',
+ " \"data-subscribable\" => variant.subscribable,\n",
+ before: " \"data-price\" => variant.price_for_options(current_pricing_options)&.money&.to_html\n"
end
def add_migrations
diff --git a/lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription.rb b/lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription.rb
index ed9cf2fb..f0f013b8 100644
--- a/lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription.rb
+++ b/lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription.rb
@@ -5,7 +5,7 @@ module CreateSubscription
include SolidusSubscriptions::SubscriptionLineItemBuilder
included do
- after_action :handle_subscription_line_items, only: :create, if: ->{ params[:subscription_line_item] }
+ after_action :handle_subscription_line_items, only: :create, if: :valid_subscription_line_item_params?
end
private
@@ -14,4 +14,9 @@ def handle_subscription_line_items
line_item = @current_order.line_items.find_by(variant_id: params[:variant_id])
create_subscription_line_item(line_item)
end
+
+ def valid_subscription_line_item_params?
+ subscription_params = params[:subscription_line_item]
+ %i[subscribable_id quantity interval_length].all? { |key| subscription_params[key].present? }
+ end
end
diff --git a/lib/generators/solidus_subscriptions/install/templates/app/views/cart_line_items/_subscription_fields.html.erb b/lib/generators/solidus_subscriptions/install/templates/app/views/cart_line_items/_subscription_fields.html.erb
index dfda14f1..2fffa2f2 100644
--- a/lib/generators/solidus_subscriptions/install/templates/app/views/cart_line_items/_subscription_fields.html.erb
+++ b/lib/generators/solidus_subscriptions/install/templates/app/views/cart_line_items/_subscription_fields.html.erb
@@ -1,39 +1,52 @@
-<% if @product.subscribable %>
- <%= content_tag :h3, t('.subscription_fields') %>
- <%= fields_for :'subscription_line_item', SolidusSubscriptions::LineItem.new do |ff| %>
-
- <%= ff.label :quantity, t('.quantity') %>
- <%= ff.number_field :quantity %>
- <%= ff.label :quantity, t('.quantity_suffix') %>
-
-
-
- <%= ff.label :interval_length, t('.interval_length') %>
- <%= ff.number_field :interval_length %>
-
- <%= ff.collection_radio_buttons :interval_units, SolidusSubscriptions::LineItem.interval_units.to_a, :first, :first %>
-
-
- <%= ff.hidden_field :subscribable_id %>
+
diff --git a/lib/solidus_subscriptions/engine.rb b/lib/solidus_subscriptions/engine.rb
index 682ebccc..f8fd7c29 100644
--- a/lib/solidus_subscriptions/engine.rb
+++ b/lib/solidus_subscriptions/engine.rb
@@ -31,9 +31,11 @@ class Engine < Rails::Engine
}
end
- initializer 'solidus_subscriptions.register_promotion_rules', after: 'spree.promo.register.promotion.rules' do |app|
- app.config.spree.promotions.rules << 'SolidusSubscriptions::Promotion::Rules::SubscriptionCreationOrder'
- app.config.spree.promotions.rules << 'SolidusSubscriptions::Promotion::Rules::SubscriptionInstallmentOrder'
+ if Object.const_defined?("Spree::Promotion")
+ initializer 'solidus_subscriptions.register_promotion_rules', after: 'spree.promo.register.promotion.rules' do |app|
+ app.config.spree.promotions.rules << 'SolidusSubscriptions::Promotion::Rules::SubscriptionCreationOrder'
+ app.config.spree.promotions.rules << 'SolidusSubscriptions::Promotion::Rules::SubscriptionInstallmentOrder'
+ end
end
initializer 'solidus_subscriptions.configure_backend' do
diff --git a/solidus_subscriptions.gemspec b/solidus_subscriptions.gemspec
index 47e3f9cd..9659c349 100644
--- a/solidus_subscriptions.gemspec
+++ b/solidus_subscriptions.gemspec
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'httparty', '~> 0.18'
spec.add_dependency 'i18n'
spec.add_dependency 'solidus_core', '>= 2.11', '< 5'
- spec.add_dependency 'solidus_support', '~> 0.9'
+ spec.add_dependency 'solidus_support', '~> 0.11'
spec.add_dependency 'state_machines'
spec.add_development_dependency 'rspec-activemodel-mocks'
diff --git a/spec/controllers/concerns/create_subscription_spec.rb b/spec/controllers/concerns/create_subscription_spec.rb
new file mode 100644
index 00000000..59338b83
--- /dev/null
+++ b/spec/controllers/concerns/create_subscription_spec.rb
@@ -0,0 +1,91 @@
+require 'spec_helper'
+require_relative '../../../lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription'
+
+RSpec.describe CreateSubscription, type: :controller do
+ subject(:controller_instance) do
+ Class.new(ApplicationController) do
+ include CreateSubscription
+ attr_accessor :params, :current_order
+
+ def initialize(params = {})
+ @params = params
+ @current_order = nil
+ end
+ end.new
+ end
+
+ let(:variant) { create(:variant) }
+ let(:order) { create(:order) }
+
+ before do
+ controller_instance.current_order = order
+ end
+
+ describe '#subscription_line_item_params_present?' do
+ context 'when all required params are present' do
+ it 'returns true' do
+ controller_instance.params = {
+ subscription_line_item: {
+ subscribable_id: 1,
+ quantity: 2,
+ interval_length: 1
+ }
+ }
+ expect(controller_instance.send(:valid_subscription_line_item_params?)).to be true
+ end
+ end
+
+ context 'when required params are missing' do
+ it 'returns false' do
+ controller_instance.params = {
+ subscription_line_item: {
+ subscribable_id: '',
+ quantity: '',
+ interval_length: ''
+ }
+ }
+ expect(controller_instance.send(:valid_subscription_line_item_params?)).to be false
+ end
+ end
+ end
+
+ describe '#handle_subscription_line_items' do
+ context 'when subscription params are missing' do
+ it 'does not invoke handle_subscription_line_items and does not create a subscription line item' do
+ order.line_items.count
+
+ controller_instance.params = {
+ variant_id: variant.id,
+ subscription_line_item: {}
+ }
+
+ expect(controller_instance.send(:valid_subscription_line_item_params?)).to be false
+
+ expect(controller_instance).not_to receive(:handle_subscription_line_items)
+
+ expect(controller_instance).not_to receive(:create_subscription_line_item)
+ end
+ end
+
+ context 'when subscription params are present' do
+ it 'calls create_subscription_line_item with the correct line item' do
+ line_item = create(:line_item, order: order, variant: variant)
+
+ controller_instance.params = {
+ variant_id: variant.id,
+ subscription_line_item: {
+ subscribable_id: 1,
+ quantity: 2,
+ interval_length: 1
+ }
+ }
+
+ allow(order.line_items).to receive(:find_by).with(variant_id: variant.id).and_return(line_item)
+
+ expect(controller_instance).to receive(:create_subscription_line_item).with(line_item)
+
+ controller_instance.send(:handle_subscription_line_items)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/spree/api/line_items_controller_spec.rb b/spec/controllers/spree/api/line_items_controller_spec.rb
index 478f9fdc..3293fc9a 100644
--- a/spec/controllers/spree/api/line_items_controller_spec.rb
+++ b/spec/controllers/spree/api/line_items_controller_spec.rb
@@ -11,7 +11,7 @@
subject(:post_create) { post :create, params: params }
let(:params) { line_item_params }
- let!(:variant) { create :variant }
+ let!(:variant) { create :variant, subscribable: true }
let!(:order) { create :order }
let(:line_item_params) do
@@ -70,7 +70,7 @@
let(:params) { line_item_params }
context 'when adding subscription information' do
- let(:variant) { create :variant }
+ let(:variant) { create :variant, subscribable: true }
let(:order) { create :order }
let(:line_item) { create :line_item, order: order, variant: variant }
let(:line_item_params) do
diff --git a/spec/controllers/spree/api/orders_controller_spec.rb b/spec/controllers/spree/api/orders_controller_spec.rb
index 5f32a569..81a0f234 100644
--- a/spec/controllers/spree/api/orders_controller_spec.rb
+++ b/spec/controllers/spree/api/orders_controller_spec.rb
@@ -8,7 +8,7 @@
routes { Spree::Core::Engine.routes }
let(:order) { create :order }
- let(:variant) { create :variant }
+ let(:variant) { create :variant, subscribable: true }
describe 'patch /update' do
subject(:subscription_line_items) do
diff --git a/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb b/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb
index 90bc9d17..67543923 100644
--- a/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb
+++ b/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb
@@ -16,7 +16,7 @@
describe 'POST /orders/populate' do
subject(:populate) { post :populate, params: params }
- let!(:variant) { create :variant }
+ let!(:variant) { create :variant, subscribable: true }
let(:params) { line_item_params }
let(:line_item_params) do
{
diff --git a/spec/jobs/solidus_subscriptions/process_subscription_job_spec.rb b/spec/jobs/solidus_subscriptions/process_subscription_job_spec.rb
index 1a3cf6fe..511c34af 100644
--- a/spec/jobs/solidus_subscriptions/process_subscription_job_spec.rb
+++ b/spec/jobs/solidus_subscriptions/process_subscription_job_spec.rb
@@ -5,7 +5,7 @@
it 'voids the actionable date of the unfulfilled installments' do
stub_config(clear_past_installments: true)
subscription = create(:subscription)
- unfulfilled_installment = create(:installment, :failed, subscription: subscription)
+ unfulfilled_installment = create(:installment, :failed, subscription: subscription)
described_class.perform_now(subscription)
diff --git a/spec/models/solidus_subscriptions/line_item_spec.rb b/spec/models/solidus_subscriptions/line_item_spec.rb
index d7c1bdba..de9bc3c2 100644
--- a/spec/models/solidus_subscriptions/line_item_spec.rb
+++ b/spec/models/solidus_subscriptions/line_item_spec.rb
@@ -26,4 +26,26 @@
expect(interval.from_now).to eq Date.parse("2016-10-22")
end
end
+
+ describe "custom validation" do
+ context "when subscribable is not true" do
+ let(:subscribable) { create(:variant, subscribable: false) }
+ let(:line_item) { build(:subscription_line_item, subscribable: subscribable) }
+
+ it "adds an error to subscribable" do
+ line_item.valid?
+ expect(line_item.errors[:subscribable]).to include("The requested item cannot be subscribed")
+ end
+ end
+
+ context "when subscribable is true" do
+ let(:subscribable) { create(:variant, subscribable: true) }
+ let(:line_item) { build(:subscription_line_item, subscribable: subscribable) }
+
+ it "does not add an error to subscribable" do
+ line_item.valid?
+ expect(line_item.errors[:subscribable]).to be_empty
+ end
+ end
+ end
end