1
- e_limit = 100
- e_limit = 1000 if u.admin?
- u.update_column :enterprise_limit, e_limit
- end
- end
- end
-
- def down
- remove_column :spree_users, :enterprise_limit
- end
-end
diff --git a/db/migrate/20140927005000_add_dummy_for_missing_emails.rb b/db/migrate/20140927005000_add_dummy_for_missing_emails.rb
deleted file mode 100644
index 08f638e2a3..0000000000
--- a/db/migrate/20140927005000_add_dummy_for_missing_emails.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class AddDummyForMissingEmails < ActiveRecord::Migration
- def up
- Enterprise.all.each do |enterprise|
- enterprise.update_column(:email, "missing@example.com") if enterprise.read_attribute(:email).blank?
- end
- end
-end
diff --git a/db/migrate/20140927005043_enterprise_config_refactor.rb b/db/migrate/20140927005043_enterprise_config_refactor.rb
deleted file mode 100644
index 6b51ac6e50..0000000000
--- a/db/migrate/20140927005043_enterprise_config_refactor.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-class EnterpriseConfigRefactor < ActiveRecord::Migration
- class Enterprise < ActiveRecord::Base
- self.inheritance_column = nil
- end
-
- def up
- add_column :enterprises, :sells, :string, null: false, default: 'none'
- add_index :enterprises, :sells
- add_index :enterprises, [:is_primary_producer, :sells]
-
- Enterprise.reset_column_information
-
- Enterprise.all.each do |enterprise|
- enterprise.update_attributes!({:sells => sells_what?(enterprise)})
- end
-
- remove_column :enterprises, :type
- remove_column :enterprises, :is_distributor
- end
-
- def down
- # This process is lossy. Producer profiles wont exist.
- add_column :enterprises, :type, :string, null: false, default: 'profile'
- add_column :enterprises, :is_distributor, :boolean
-
- Enterprise.reset_column_information
-
- Enterprise.all.each do |enterprise|
- enterprise.update_attributes!({
- :type => type?(enterprise),
- :is_distributor => distributes?(enterprise)
- })
- end
-
- remove_column :enterprises, :sells
- end
-
- def sells_what?(enterprise)
- is_distributor = enterprise.read_attribute(:is_distributor)
- is_primary_producer = enterprise.read_attribute(:is_primary_producer)
- type = enterprise.read_attribute(:type)
- return "own" if type == "single" && (is_distributor || is_primary_producer)
- return "none" if !is_distributor || type == "profile"
- return "any"
- end
-
- def distributes?(enterprise)
- enterprise.read_attribute(:sells) != "none"
- end
-
- def type?(enterprise)
- sells = enterprise.read_attribute(:sells)
- return "profile" if sells == "none"
- return "single" if sells == "own"
- return "full"
- end
-end
diff --git a/db/migrate/20141003060622_add_standard_variant_to_products.rb b/db/migrate/20141003060622_add_standard_variant_to_products.rb
deleted file mode 100644
index 5242f86686..0000000000
--- a/db/migrate/20141003060622_add_standard_variant_to_products.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-class AddStandardVariantToProducts < ActiveRecord::Migration
- def up
- # Make sure that all products have a variant_unit
- Spree::Product.where("variant_unit IS NULL OR variant_unit = ''").update_all(variant_unit: "items", variant_unit_name: "each")
-
- # Find products without any standard variants
- products_with_only_master = Spree::Product.includes(:variants).where('spree_variants.id IS NULL').select('DISTINCT spree_products.*')
-
- products_with_only_master.each do |product|
- # Add a unit_value to the master variant if it doesn't have one
- if product.unit_value.blank?
- if product.variant_unit == "weight" && match = product.unit_description.andand.match(/^(\d+(\.\d*)?)(k?g) ?(.*)$/)
- scale = (match[3] == "kg" ? 1000 : 1)
- product.unit_value = (match[1].to_i*scale)
- product.unit_description = match[4]
- product.save!
- else
- unless product.variant_unit == "items" && product.unit_description.present?
- product.unit_value = 1
- product.save!
- end
- end
- end
-
- # Run the callback to add a copy of the master variant as a standard variant
- product.send(:ensure_standard_variant)
-
- existing_master = product.master
- new_variant = product.variants.first
-
- # Replace any relevant references to the master variant with the new standard variant
-
- # Inventory Units
- # Strategy: do nothing to inventory units pertaining to existing_master,
- # new inventory units will be created with reference to new_variant
-
- # Line Items
- # Strategy: do nothing to line items pertaining to existing_master,
- # new line items will be created with reference to new_variant
-
- # Option Values
- # Strategy: add all option values on existing_master to new_variant, and keep on existing_master
- option_values = existing_master.option_values
- option_values.each do |option_value|
- variant_ids = option_value.variant_ids
- variant_ids << new_variant.id
- option_value.update_attributes(variant_ids: variant_ids)
- end
-
- # Prices
- # Strategy: duplicate all prices on existing_master and assign them to new_variant
- existing_prices = existing_master.prices
- existing_prices.each do |price|
- new_variant.prices << price.dup
- end
-
- # Exchange Variants
- # Strategy: Replace all references to existing master in exchanges with new_variant
- exchange_variants = ExchangeVariant.where(variant_id: existing_master.id)
- exchange_variants.update_all(variant_id: new_variant.id)
- end
- end
-end
diff --git a/db/migrate/20141010043405_add_confirmable_to_enterprise.rb b/db/migrate/20141010043405_add_confirmable_to_enterprise.rb
deleted file mode 100644
index 9c29bd5f2c..0000000000
--- a/db/migrate/20141010043405_add_confirmable_to_enterprise.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class AddConfirmableToEnterprise < ActiveRecord::Migration
- def up
- add_column :enterprises, :confirmation_token, :string
- add_column :enterprises, :confirmed_at, :datetime
- add_column :enterprises, :confirmation_sent_at, :datetime
- add_column :enterprises, :unconfirmed_email, :string
- add_index :enterprises, :confirmation_token, :unique => true
-
- # Existing enterprises are assumed to be confirmed
- Enterprise.update_all(:confirmed_at => Time.zone.now)
- end
-
- def down
- remove_columns :enterprises, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email
- end
-end
diff --git a/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb b/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb
deleted file mode 100644
index c9680f4e40..0000000000
--- a/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddShopTrialStartDateToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :shop_trial_start_date, :datetime, default: nil
- end
-end
diff --git a/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb b/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb
deleted file mode 100644
index fb73d123f8..0000000000
--- a/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddProducerProfileOnlyToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :producer_profile_only, :boolean, default: false
- end
-end
diff --git a/db/migrate/20141113053004_create_variant_overrides.rb b/db/migrate/20141113053004_create_variant_overrides.rb
deleted file mode 100644
index ae3746f828..0000000000
--- a/db/migrate/20141113053004_create_variant_overrides.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class CreateVariantOverrides < ActiveRecord::Migration
- def change
- create_table :variant_overrides do |t|
- t.references :variant
- t.references :hub
- t.decimal :price, precision: 8, scale: 2
- t.integer :count_on_hand
- end
-
- add_foreign_key :variant_overrides, :spree_variants, column: :variant_id
- add_foreign_key :variant_overrides, :enterprises, column: :hub_id
-
- add_index :variant_overrides, [:variant_id, :hub_id]
- end
-end
diff --git a/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb b/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb
deleted file mode 100644
index b2f50167c9..0000000000
--- a/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class AddNotNullToVariantOverrideRelations < ActiveRecord::Migration
- def up
- change_column :variant_overrides, :hub_id, :integer, null: false
- change_column :variant_overrides, :variant_id, :integer, null: false
- end
-
- def down
- change_column :variant_overrides, :hub_id, :integer, null: true
- change_column :variant_overrides, :variant_id, :integer, null: true
- end
-end
diff --git a/db/migrate/20141219034321_add_permalink_to_enterprises.rb b/db/migrate/20141219034321_add_permalink_to_enterprises.rb
deleted file mode 100644
index 850e1cf171..0000000000
--- a/db/migrate/20141219034321_add_permalink_to_enterprises.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-class AddPermalinkToEnterprises < ActiveRecord::Migration
- def up
- add_column :enterprises, :permalink, :string
-
- Enterprise.reset_column_information
-
- Enterprise.all.each do |enterprise|
- counter = 1
- permalink = enterprise.name.parameterize
- permalink = "my-enterprise-name" if permalink == ""
- while Enterprise.find_by(permalink: permalink) do
- permalink = enterprise.name.parameterize + counter.to_s
- counter += 1
- end
-
- enterprise.update_column :permalink, permalink
- end
-
- change_column :enterprises, :permalink, :string, null: false
- end
-
- def down
- remove_column :enterprises, :permalink
- end
-end
diff --git a/db/migrate/20141229094516_add_receival_time_to_exchange.rb b/db/migrate/20141229094516_add_receival_time_to_exchange.rb
deleted file mode 100644
index 06933ed051..0000000000
--- a/db/migrate/20141229094516_add_receival_time_to_exchange.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddReceivalTimeToExchange < ActiveRecord::Migration
- def change
- add_column :exchanges, :receival_time, :string
- add_column :exchanges, :receival_instructions, :string
- end
-end
diff --git a/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb b/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb
deleted file mode 100644
index 566b35bb88..0000000000
--- a/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddAddressesRefToEnterpriseGroups < ActiveRecord::Migration
- def change
- add_column :enterprise_groups, :address_id, :integer
- add_foreign_key :enterprise_groups, :spree_addresses, column: "address_id"
- end
-end
diff --git a/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb b/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb
deleted file mode 100644
index 0ef08a39dc..0000000000
--- a/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-class AddAddressInstancesToExistingEnterpriseGroups < ActiveRecord::Migration
- def change
- country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE'])
- state = country.states.first
- EnterpriseGroup.all.each do |g|
- next if g.address.present?
- address = Spree::Address.new(firstname: 'unused', lastname: 'unused', address1: 'undefined', city: 'undefined', zipcode: 'undefined', state: state, country: country, phone: 'undefined')
- g.address = address
- # some groups are invalid, because of a missing description
- g.save!(validate: false)
- end
- end
-
- def self.down
- # we can't know which addresses were already there and which weren't
- # and we can't remove addresses as long as they are referenced and
- # required by the model
- end
-end
diff --git a/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb b/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb
deleted file mode 100644
index afea2dbeea..0000000000
--- a/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class AddWebContactToEnterpriseGroups < ActiveRecord::Migration
- def change
- add_column :enterprise_groups, :email, :string, null: false, default: ''
- add_column :enterprise_groups, :website, :string, null: false, default: ''
- add_column :enterprise_groups, :facebook, :string, null: false, default: ''
- add_column :enterprise_groups, :instagram, :string, null: false, default: ''
- add_column :enterprise_groups, :linkedin, :string, null: false, default: ''
- add_column :enterprise_groups, :twitter, :string, null: false, default: ''
- end
-end
diff --git a/db/migrate/20150122145607_create_customers.rb b/db/migrate/20150122145607_create_customers.rb
deleted file mode 100644
index 12e5a721e8..0000000000
--- a/db/migrate/20150122145607_create_customers.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-class CreateCustomers < ActiveRecord::Migration
- def change
- create_table :customers do |t|
- t.string :email, null: false
- t.references :enterprise, null: false
- t.string :code, null: false
- t.references :user
-
- t.timestamps
- end
- add_index :customers, [:enterprise_id, :code], unique: true
- add_index :customers, :email
- add_index :customers, :user_id
-
- add_foreign_key :customers, :enterprises, column: :enterprise_id
- add_foreign_key :customers, :spree_users, column: :user_id
- end
-end
diff --git a/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb b/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb
deleted file mode 100644
index f2e46452df..0000000000
--- a/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddOwnerToEnterpriseGroups < ActiveRecord::Migration
- def change
- add_column :enterprise_groups, :owner_id, :integer
- add_foreign_key :enterprise_groups, :spree_users, column: "owner_id"
- end
-end
diff --git a/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb b/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb
deleted file mode 100644
index 89035fc16f..0000000000
--- a/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddTemperatureControlledToSpreeShippingCategories < ActiveRecord::Migration
- def change
- add_column :spree_shipping_categories, :temperature_controlled, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb b/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb
deleted file mode 100644
index 062e9523e6..0000000000
--- a/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddOwnerIndexToEnterpriseGroups < ActiveRecord::Migration
- def change
- add_index :enterprise_groups, :owner_id
- end
-end
diff --git a/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb b/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb
deleted file mode 100644
index 32094cbde7..0000000000
--- a/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAddressIdIndexToEnterpriseGroups < ActiveRecord::Migration
- def change
- add_index :enterprise_groups, :address_id
- end
-end
diff --git a/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb b/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb
deleted file mode 100644
index 05b5410587..0000000000
--- a/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class AddTaxCategoryToEnterpriseFee < ActiveRecord::Migration
- def change
- add_column :enterprise_fees, :tax_category_id, :integer
- add_foreign_key :enterprise_fees, :spree_tax_categories, column: :tax_category_id
- add_index :enterprise_fees, :tax_category_id
- end
-end
diff --git a/db/migrate/20150225232938_add_included_tax_to_adjustments.rb b/db/migrate/20150225232938_add_included_tax_to_adjustments.rb
deleted file mode 100644
index f3815dec2a..0000000000
--- a/db/migrate/20150225232938_add_included_tax_to_adjustments.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddIncludedTaxToAdjustments < ActiveRecord::Migration
- def change
- add_column :spree_adjustments, :included_tax, :decimal, precision: 10, scale: 2, null: false, default: 0
- end
-end
diff --git a/db/migrate/20150305004846_add_weight_to_line_items.rb b/db/migrate/20150305004846_add_weight_to_line_items.rb
deleted file mode 100644
index a4df1a12f0..0000000000
--- a/db/migrate/20150305004846_add_weight_to_line_items.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddWeightToLineItems < ActiveRecord::Migration
- def change
- add_column :spree_line_items, :unit_value, :decimal, :precision => 8, :scale => 2
- end
-end
diff --git a/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb b/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb
deleted file mode 100644
index ba8dfa7a08..0000000000
--- a/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddChargesSalesTaxToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :charges_sales_tax, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20150410043302_create_delayed_jobs.rb b/db/migrate/20150410043302_create_delayed_jobs.rb
deleted file mode 100644
index f7de70bdc5..0000000000
--- a/db/migrate/20150410043302_create_delayed_jobs.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class CreateDelayedJobs < ActiveRecord::Migration
- def self.up
- create_table :delayed_jobs, :force => true do |table|
- table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
- table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
- table.text :handler, :null => false # YAML-encoded string of the object that will do work
- table.text :last_error # reason for last failure (See Note below)
- table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
- table.datetime :locked_at # Set when a client is working on this object
- table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
- table.string :locked_by # Who is working on this object (if locked)
- table.string :queue # The name of the queue this job is in
- table.timestamps
- end
-
- add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
- end
-
- def self.down
- drop_table :delayed_jobs
- end
-end
diff --git a/db/migrate/20150422014819_add_inherits_properties_to_product.rb b/db/migrate/20150422014819_add_inherits_properties_to_product.rb
deleted file mode 100644
index aba8bbbe45..0000000000
--- a/db/migrate/20150422014819_add_inherits_properties_to_product.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddInheritsPropertiesToProduct < ActiveRecord::Migration
- def change
- add_column :spree_products, :inherits_properties, :boolean, null: false, default: true
- end
-end
diff --git a/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb b/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb
deleted file mode 100644
index 8c5a2d1f2c..0000000000
--- a/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class AddDefaultAndNotNullToProducerPropertiesPosition < ActiveRecord::Migration
- def change
- ProducerProperty.where(position: nil).each do |producer_property|
- producer_property.update_attribute(:position, 0)
- end
-
- change_column :producer_properties, :position, :integer, null: false, default: 0
- end
-end
diff --git a/db/migrate/20150424151117_populate_line_item_unit_value.rb b/db/migrate/20150424151117_populate_line_item_unit_value.rb
deleted file mode 100644
index 2122b84472..0000000000
--- a/db/migrate/20150424151117_populate_line_item_unit_value.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class PopulateLineItemUnitValue < ActiveRecord::Migration
- def up
- execute "UPDATE spree_line_items SET unit_value = spree_variants.unit_value FROM spree_variants WHERE spree_line_items.variant_id = spree_variants.id"
- end
-
- def down
- raise ActiveRecord::IrreversibleMigration
- end
-end
diff --git a/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 6bbd5594ea..0000000000
--- a/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 1)
-class ActsAsTaggableOnMigration < ActiveRecord::Migration
- def self.up
- create_table :tags do |t|
- t.string :name
- end
-
- create_table :taggings do |t|
- t.references :tag
-
- # You should make sure that the column created is
- # long enough to store the required class names.
- t.references :taggable, polymorphic: true
- t.references :tagger, polymorphic: true
-
- # Limit is created to prevent MySQL error on index
- # length for MyISAM table type: http://bit.ly/vgW2Ql
- t.string :context, limit: 128
-
- t.datetime :created_at
- end
-
- add_index :taggings, :tag_id
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-
- def self.down
- drop_table :taggings
- drop_table :tags
- end
-end
diff --git a/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 4ca676f6c7..0000000000
--- a/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 2)
-class AddMissingUniqueIndices < ActiveRecord::Migration
- def self.up
- add_index :tags, :name, unique: true
-
- remove_index :taggings, :tag_id
- remove_index :taggings, [:taggable_id, :taggable_type, :context]
- add_index :taggings,
- [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
- unique: true, name: 'taggings_idx'
- end
-
- def self.down
- remove_index :tags, :name
-
- remove_index :taggings, name: 'taggings_idx'
- add_index :taggings, :tag_id
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-end
diff --git a/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 8edb508078..0000000000
--- a/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 3)
-class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
- def self.up
- add_column :tags, :taggings_count, :integer, default: 0
-
- ActsAsTaggableOn::Tag.reset_column_information
- ActsAsTaggableOn::Tag.find_each do |tag|
- ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
- end
- end
-
- def self.down
- remove_column :tags, :taggings_count
- end
-end
diff --git a/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb
deleted file mode 100644
index 71f2d7f433..0000000000
--- a/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 4)
-class AddMissingTaggableIndex < ActiveRecord::Migration
- def self.up
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-
- def self.down
- remove_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-end
diff --git a/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
deleted file mode 100644
index bfb06bc7cd..0000000000
--- a/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# This migration comes from acts_as_taggable_on_engine (originally 5)
-# This migration is added to circumvent issue #623 and have special characters
-# work properly
-class ChangeCollationForTagNames < ActiveRecord::Migration
- def up
- if ActsAsTaggableOn::Utils.using_mysql?
- execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
- end
- end
-end
diff --git a/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb b/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb
deleted file mode 100644
index deeacbc608..0000000000
--- a/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RemoveCustomerCodeNotNullConstraint < ActiveRecord::Migration
- def up
- change_column :customers, :code, :string, null: true
- end
-
- def down
- change_column :customers, :code, :string, null: false
- end
-end
diff --git a/db/migrate/20150508072938_add_customer_to_orders.rb b/db/migrate/20150508072938_add_customer_to_orders.rb
deleted file mode 100644
index e961840255..0000000000
--- a/db/migrate/20150508072938_add_customer_to_orders.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class AddCustomerToOrders < ActiveRecord::Migration
- def change
- add_column :spree_orders, :customer_id, :integer
- add_index :spree_orders, :customer_id
- add_foreign_key :spree_orders, :customers, column: :customer_id
-
- Spree::Order.where("spree_orders.email IS NOT NULL AND distributor_id IS NOT NULL AND customer_id IS NULL").each do |order|
- customer = Customer.find_by(email: order.email, enterprise_id: order.distributor_id)
- unless customer.present?
- user = Spree::User.find_by(email: order.email)
- customer = Customer.create!(email: order.email, enterprise_id: order.distributor_id, user_id: user.andand.id )
- end
- order.update_attribute(:customer, customer)
- end
- end
-end
diff --git a/db/migrate/20150527004427_add_permalink_to_groups.rb b/db/migrate/20150527004427_add_permalink_to_groups.rb
deleted file mode 100644
index df40798492..0000000000
--- a/db/migrate/20150527004427_add_permalink_to_groups.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-class AddPermalinkToGroups < ActiveRecord::Migration
- def up
- add_column :enterprise_groups, :permalink, :string
-
- EnterpriseGroup.reset_column_information
-
- EnterpriseGroup.all.each do |group|
- counter = 1
- permalink = group.name.parameterize
- permalink = "my-group-name" if permalink == ""
- while EnterpriseGroup.find_by(permalink: permalink) do
- permalink = group.name.parameterize + counter.to_s
- counter += 1
- end
-
- group.update_column :permalink, permalink
- end
-
- change_column :enterprise_groups, :permalink, :string, null: false
- add_index :enterprise_groups, :permalink, :unique => true
- end
-
- def down
- remove_column :enterprise_groups, :permalink
- end
-end
diff --git a/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb b/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb
deleted file mode 100644
index e8841b2c5f..0000000000
--- a/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class AddUniqueIndexToEnterprisePermalink < ActiveRecord::Migration
- def change
- duplicates = Enterprise.group(:permalink).having('count(*) > 1').pluck(:permalink)
- duplicates.each { |p| resolve_permalink(p) };
- add_index :enterprises, :permalink, :unique => true
- end
-
- def resolve_permalink(permalink)
- conflicting = Enterprise.where(permalink: permalink)
- while conflicting.size > 1 do
- enterprise = conflicting.pop
- enterprise.permalink = nil
- enterprise.save
- end
- end
-end
diff --git a/db/migrate/20150604045725_add_sessions_table.rb b/db/migrate/20150604045725_add_sessions_table.rb
deleted file mode 100644
index 4c879564a5..0000000000
--- a/db/migrate/20150604045725_add_sessions_table.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddSessionsTable < ActiveRecord::Migration
- def change
- create_table :sessions do |t|
- t.string :session_id, :null => false
- t.text :data
- t.timestamps
- end
-
- add_index :sessions, :session_id
- add_index :sessions, :updated_at
- end
-end
diff --git a/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb b/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb
deleted file mode 100644
index ee9d8d4af8..0000000000
--- a/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class DependentDeleteAdjustmentMetadata < ActiveRecord::Migration
- def up
- remove_foreign_key "adjustment_metadata", name: "adjustment_metadata_adjustment_id_fk"
- add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id", dependent: :delete
- end
-
- def down
- remove_foreign_key "adjustment_metadata", name: "adjustment_metadata_adjustment_id_fk"
- add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id"
- end
-end
diff --git a/db/migrate/20150612045544_make_enterprises_name_unique.rb b/db/migrate/20150612045544_make_enterprises_name_unique.rb
deleted file mode 100644
index da92f6a8fe..0000000000
--- a/db/migrate/20150612045544_make_enterprises_name_unique.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class MakeEnterprisesNameUnique < ActiveRecord::Migration
- def up
- dup_names = Enterprise.group('name').select('name, COUNT(*) AS num_enterprises')
-
- dup_names.each do |data|
- (data.num_enterprises.to_i - 1).times do |i|
- e = Enterprise.find_by name: data.name
- new_name = "#{data.name}-#{i+1}"
- e.update_column :name, new_name
- say "Renamed enterprise #{data.name} to #{new_name}"
- end
- end
-
- add_index :enterprises, :name, unique: true
- end
-
- def down
- remove_index :enterprises, :name
- end
-end
diff --git a/db/migrate/20150619020711_create_versions.rb b/db/migrate/20150619020711_create_versions.rb
deleted file mode 100644
index 23be970c66..0000000000
--- a/db/migrate/20150619020711_create_versions.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateVersions < ActiveRecord::Migration
- def change
- create_table :versions do |t|
- t.string :item_type, :null => false
- t.integer :item_id, :null => false
- t.string :event, :null => false
- t.string :whodunnit
- t.text :object
- t.datetime :created_at
- end
- add_index :versions, [:item_type, :item_id]
- end
-end
diff --git a/db/migrate/20150619100137_create_bill_items.rb b/db/migrate/20150619100137_create_bill_items.rb
deleted file mode 100644
index fec80692b1..0000000000
--- a/db/migrate/20150619100137_create_bill_items.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class CreateBillItems < ActiveRecord::Migration
- def change
- create_table :bill_items do |t|
- t.references :enterprise, nil: false
- t.references :owner, nil: false
- t.datetime :begins_at, default: nil
- t.datetime :ends_at, default: nil
- t.string :sells, default: nil
- t.boolean :trial, default: false
- t.decimal :turnover, default: 0.0
- t.foreign_key :enterprises
- t.foreign_key :spree_users, column: :owner_id
- end
- end
-end
diff --git a/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb b/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb
deleted file mode 100644
index caa2fb9a4d..0000000000
--- a/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RenameBillItemsToBillablePeriods < ActiveRecord::Migration
- def up
- rename_table :bill_items, :billable_periods
- end
-
- def down
- rename_table :billable_periods, :bill_items
- end
-end
diff --git a/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb b/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb
deleted file mode 100644
index 6c3ea52356..0000000000
--- a/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class AddTimestampsToBillablePeriods < ActiveRecord::Migration
- def change
- change_table(:billable_periods) do |t|
- t.datetime :deleted_at, default: nil
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb b/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb
deleted file mode 100644
index 880a1b8349..0000000000
--- a/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddDefaultStockToVariantOverrides < ActiveRecord::Migration
- def change
- add_column :variant_overrides, :default_stock, :integer
- end
-end
diff --git a/db/migrate/20150719153136_rename_line_item_unit_value.rb b/db/migrate/20150719153136_rename_line_item_unit_value.rb
deleted file mode 100644
index 9dbdce75c5..0000000000
--- a/db/migrate/20150719153136_rename_line_item_unit_value.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class RenameLineItemUnitValue < ActiveRecord::Migration
- def change
- rename_column :spree_line_items, :unit_value, :final_weight_volume
- end
-end
diff --git a/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb b/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb
deleted file mode 100644
index c1b3482c0f..0000000000
--- a/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class UpdatePrecisionOnLineItemFinalWeightVolume < ActiveRecord::Migration
- def up
- change_column :spree_line_items, :final_weight_volume, :decimal, :precision => 10, :scale => 2
- end
-
- def down
- raise ActiveRecord::IrreversibleMigration
- end
-end
-
-
diff --git a/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb b/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb
deleted file mode 100644
index 4d51a7160b..0000000000
--- a/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class UpdateSpreeLineItemFinalWeightVolume < ActiveRecord::Migration
- def up
- execute "UPDATE spree_line_items SET final_weight_volume = final_weight_volume * quantity"
- end
-
- def down
- raise ActiveRecord::IrreversibleMigration
- end
-end
diff --git a/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb b/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb
deleted file mode 100644
index 172cce6588..0000000000
--- a/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddEnableResetToVariantOverrides < ActiveRecord::Migration
- def change
- add_column :variant_overrides, :enable_reset, :boolean
- end
-end
diff --git a/db/migrate/20150916012814_create_account_invoices.rb b/db/migrate/20150916012814_create_account_invoices.rb
deleted file mode 100644
index 7e92a53593..0000000000
--- a/db/migrate/20150916012814_create_account_invoices.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-class CreateAccountInvoices < ActiveRecord::Migration
- def change
- create_table :account_invoices do |t|
- t.references :user, null: false
- t.references :order
- t.integer :year, null: false
- t.integer :month, null: false
- t.datetime :issued_at
-
- t.timestamps
- end
- add_index :account_invoices, :user_id
- add_index :account_invoices, :order_id
-
- add_foreign_key :account_invoices, :spree_orders, column: :order_id
- add_foreign_key :account_invoices, :spree_users, column: :user_id
- end
-end
diff --git a/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb b/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb
deleted file mode 100644
index ee1d9d5d93..0000000000
--- a/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class AddAccountInvoiceToBillablePeriods < ActiveRecord::Migration
- def change
- add_column :billable_periods, :account_invoice_id, :integer, null: false
- add_index :billable_periods, :account_invoice_id
- add_foreign_key :billable_periods, :account_invoices, column: :account_invoice_id
- end
-end
diff --git a/db/migrate/20150924054538_add_option_values_line_items_join_table.rb b/db/migrate/20150924054538_add_option_values_line_items_join_table.rb
deleted file mode 100644
index 7a51c851ec..0000000000
--- a/db/migrate/20150924054538_add_option_values_line_items_join_table.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class AddOptionValuesLineItemsJoinTable < ActiveRecord::Migration
- def change
- create_table :spree_option_values_line_items, :id => false, :force => true do |t|
- t.integer :line_item_id
- t.integer :option_value_id
- end
-
- Spree::LineItem.all.each do |line_item|
- line_item.update_units
- end
-
- add_index :spree_option_values_line_items, :line_item_id, :name => 'index_option_values_line_items_on_line_item_id'
- end
-end
diff --git a/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb b/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb
deleted file mode 100644
index 6d2c7d45c5..0000000000
--- a/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class EnsureAddressForAccountInvoiceOrders < ActiveRecord::Migration
- def up
- AccountInvoice.where('order_id IS NOT NULL').each do |account_invoice|
- billable_periods = account_invoice.billable_periods.order(:enterprise_id).reject{ |bp| bp.turnover == 0 }
-
- if billable_periods.any?
- address = billable_periods.first.enterprise.address
- account_invoice.order.update_attributes(bill_address: address, ship_address: address)
- end
- end
- end
-
- def down
- end
-end
diff --git a/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb b/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb
deleted file mode 100644
index 434a2053ab..0000000000
--- a/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class CombineExchangeReceivalTimeReceivalInstructions < ActiveRecord::Migration
- def up
- remove_column :exchanges, :receival_time
- end
-
- def down
- add_column :exchanges, :receival_time, :string
- end
-end
diff --git a/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb b/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb
deleted file mode 100644
index 9c47bfbc27..0000000000
--- a/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddOnDemandAndSkuToVariantOverrides < ActiveRecord::Migration
- def change
- add_column :variant_overrides, :sku, :string, :default => nil, :after => :hub_id
- add_column :variant_overrides, :on_demand, :boolean, :default => nil, :after => :count_on_hand
- end
-end
diff --git a/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb b/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb
deleted file mode 100644
index 461e2efe25..0000000000
--- a/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class RenameEnableResetToResettable < ActiveRecord::Migration
- rename_column :variant_overrides, :enable_reset, :resettable
-end
diff --git a/db/migrate/20160114001844_create_inventory_items.rb b/db/migrate/20160114001844_create_inventory_items.rb
deleted file mode 100644
index 2ca54dce4d..0000000000
--- a/db/migrate/20160114001844_create_inventory_items.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateInventoryItems < ActiveRecord::Migration
- def change
- create_table :inventory_items do |t|
- t.references :enterprise, null: false, index: true
- t.references :variant, null: false, index: true
- t.boolean :visible, default: true, null: false
-
- t.timestamps
- end
-
- add_index "inventory_items", [:enterprise_id, :variant_id], unique: true
- end
-end
diff --git a/db/migrate/20160116024333_create_column_preferences.rb b/db/migrate/20160116024333_create_column_preferences.rb
deleted file mode 100644
index e38c51d858..0000000000
--- a/db/migrate/20160116024333_create_column_preferences.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class CreateColumnPreferences < ActiveRecord::Migration
- def change
- create_table :column_preferences do |t|
- t.references :user, null: false, index: true
- t.string :action_name, null: false, index: true
- t.string :column_name, null: false
- t.boolean :visible, null: false
-
- t.timestamps
- end
- add_index :column_preferences, [:user_id, :action_name, :column_name], unique: true, name: 'index_column_prefs_on_user_id_and_action_name_and_column_name'
- end
-end
diff --git a/db/migrate/20160204013914_add_id_to_coordinator_fees.rb b/db/migrate/20160204013914_add_id_to_coordinator_fees.rb
deleted file mode 100644
index 74326a6006..0000000000
--- a/db/migrate/20160204013914_add_id_to_coordinator_fees.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddIdToCoordinatorFees < ActiveRecord::Migration
- def change
- add_column :coordinator_fees, :id, :primary_key
- end
-end
diff --git a/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb b/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb
deleted file mode 100644
index 49751cc479..0000000000
--- a/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddInheritsTaxCategoryToEnterpriseFees < ActiveRecord::Migration
- def change
- add_column :enterprise_fees, :inherits_tax_category, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20160205044930_add_email_address_to_enterprises.rb b/db/migrate/20160205044930_add_email_address_to_enterprises.rb
deleted file mode 100644
index b1047fe4b8..0000000000
--- a/db/migrate/20160205044930_add_email_address_to_enterprises.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddEmailAddressToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :email_address, :string
- end
-end
diff --git a/db/migrate/20160212092908_set_enterprise_email_address.rb b/db/migrate/20160212092908_set_enterprise_email_address.rb
deleted file mode 100644
index a43591624a..0000000000
--- a/db/migrate/20160212092908_set_enterprise_email_address.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class SetEnterpriseEmailAddress < ActiveRecord::Migration
- def up
- Enterprise.all.each do |enterprise|
- enterprise.email_address = enterprise.email
- enterprise.save
- end
- end
-end
diff --git a/db/migrate/20160218235221_populate_inventories.rb b/db/migrate/20160218235221_populate_inventories.rb
deleted file mode 100644
index 2b9d1be8b6..0000000000
--- a/db/migrate/20160218235221_populate_inventories.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class PopulateInventories < ActiveRecord::Migration
- def up
- # If hubs are actively using overrides, populate their inventories with all variants they have permission to override
- # Otherwise leave their inventories empty
-
- hubs_using_overrides = Enterprise.joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.hub_id = enterprises.id")
- .where("variant_overrides.id IS NOT NULL").select("DISTINCT enterprises.*")
-
- hubs_using_overrides.each do |hub|
- overridable_producers = OpenFoodNetwork::Permissions.new(hub.owner).variant_override_producers
-
- variants = Spree::Variant.where(is_master: false, product_id: Spree::Product.not_deleted.where(supplier_id: overridable_producers))
-
- variants.each do |variant|
- InventoryItem.create(enterprise: hub, variant: variant, visible: true)
- end
- end
- end
-
- def down
- end
-end
diff --git a/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb b/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb
deleted file mode 100644
index e66c5ee7db..0000000000
--- a/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-class GrantExplicitVariantOverridePermissions < ActiveRecord::Migration
- def up
- hubs = Enterprise.is_distributor
-
- begin
- EnterpriseRelationship.skip_callback :save, :after, :apply_variant_override_permissions
-
- hubs.each do |hub|
- next if hub.owner.admin?
- explicitly_granting_producer_ids = hub.relationships_as_child
- .with_permission(:create_variant_overrides).map(&:parent_id)
-
- managed_producer_ids = Enterprise.managed_by(hub.owner).is_primary_producer.pluck(:id)
- implicitly_granting_producer_ids = managed_producer_ids - explicitly_granting_producer_ids - [hub.id]
-
- # create explicit VO permissions for producers currently granting implicit permission
- Enterprise.where(id: implicitly_granting_producer_ids).each do |producer|
- relationship = producer.relationships_as_parent.find_or_initialize_by(child_id: hub.id)
- permission = relationship.permissions.find_or_initialize_by(name: :create_variant_overrides)
- relationship.save! unless permission.persisted?
- end
- end
- ensure
- EnterpriseRelationship.set_callback :save, :after, :apply_variant_override_permissions
- end
- end
-
- def down
- end
-end
diff --git a/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb b/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb
deleted file mode 100644
index afa58ebe26..0000000000
--- a/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-class AddPermissionRevokedAtToVariantOverrides < ActiveRecord::Migration
- def up
- add_column :variant_overrides, :permission_revoked_at, :datetime, default: nil
-
- variant_override_hubs = Enterprise.where(id: VariantOverride.all.map(&:hub_id).uniq)
-
- variant_override_hubs.each do |hub|
- permitting_producer_ids = hub.relationships_as_child
- .with_permission(:create_variant_overrides).map(&:parent_id)
-
- variant_overrides_with_revoked_permissions = VariantOverride.for_hubs(hub)
- .joins(variant: :product).where("spree_products.supplier_id NOT IN (?)", permitting_producer_ids)
-
- variant_overrides_with_revoked_permissions.update_all(permission_revoked_at: Time.now)
- end
- end
-
- def down
- remove_column :variant_overrides, :permission_revoked_at
- end
-end
diff --git a/db/migrate/20160302044850_repopulate_inventories.rb b/db/migrate/20160302044850_repopulate_inventories.rb
deleted file mode 100644
index e38628439a..0000000000
--- a/db/migrate/20160302044850_repopulate_inventories.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-class RepopulateInventories < ActiveRecord::Migration
- # Previous version of this migration (20160218235221) relied on Permissions#variant_override_producers
- # which was then changed, meaning that an incomplete set of variants were added to inventories of most hubs
- # Re-running this now will ensure that all permitted variants (including those allowed by 20160224034034) are
- # added to the relevant inventories
-
- def up
- # If hubs are actively using overrides, populate their inventories with all variants they have permission to override
- # Otherwise leave their inventories empty
-
- hubs_using_overrides = Enterprise.joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.hub_id = enterprises.id")
- .where("variant_overrides.id IS NOT NULL").select("DISTINCT enterprises.*")
-
- hubs_using_overrides.each do |hub|
- overridable_producer_ids = hub.relationships_as_child.with_permission(:create_variant_overrides).map(&:parent_id) | [hub.id]
-
- variants = Spree::Variant.where(is_master: false, product_id: Spree::Product.not_deleted.where(supplier_id: overridable_producer_ids))
-
- variants_to_add = variants.joins("LEFT OUTER JOIN (SELECT * from inventory_items WHERE enterprise_id = #{hub.id}) AS o_inventory_items ON o_inventory_items.variant_id = spree_variants.id")
- .where('o_inventory_items.id IS NULL')
-
- variants_to_add.each do |variant|
- inventory_item = InventoryItem.create(enterprise: hub, variant: variant, visible: true)
- end
- end
- end
-
- def down
- end
-end
diff --git a/db/migrate/20160303004210_create_tag_rules.rb b/db/migrate/20160303004210_create_tag_rules.rb
deleted file mode 100644
index 157fee1e69..0000000000
--- a/db/migrate/20160303004210_create_tag_rules.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class CreateTagRules < ActiveRecord::Migration
- def change
- create_table :tag_rules do |t|
- t.references :enterprise, null: false, index: true
- t.string :type, null: false
-
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20160316051131_add_require_login_to_enterprise.rb b/db/migrate/20160316051131_add_require_login_to_enterprise.rb
deleted file mode 100644
index 68de642b62..0000000000
--- a/db/migrate/20160316051131_add_require_login_to_enterprise.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddRequireLoginToEnterprise < ActiveRecord::Migration
- def change
- add_column :enterprises, :require_login, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb b/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb
deleted file mode 100644
index e03ed25f9e..0000000000
--- a/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class ChangeValueTypeOfPaypalPasswords < ActiveRecord::Migration
- def up
- Spree::Preference
- .where("key like ?", "spree/gateway/pay_pal_express/password/%")
- .where(value_type: "string")
- .update_all(value_type: "password")
- end
-
- def down
- Spree::Preference
- .where("key like ?", "spree/gateway/pay_pal_express/password/%")
- .where(value_type: "password")
- .update_all(value_type: "string")
- end
-end
diff --git a/db/migrate/20160520065217_add_is_default_to_tag_rule.rb b/db/migrate/20160520065217_add_is_default_to_tag_rule.rb
deleted file mode 100644
index 209520b693..0000000000
--- a/db/migrate/20160520065217_add_is_default_to_tag_rule.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddIsDefaultToTagRule < ActiveRecord::Migration
- def change
- add_column :tag_rules, :is_default, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20160527012603_add_priority_to_tag_rule.rb b/db/migrate/20160527012603_add_priority_to_tag_rule.rb
deleted file mode 100644
index 7080d7a9ac..0000000000
--- a/db/migrate/20160527012603_add_priority_to_tag_rule.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddPriorityToTagRule < ActiveRecord::Migration
- def change
- add_column :tag_rules, :priority, :integer, default: 99, null: false
- end
-end
diff --git a/db/migrate/20160630052453_create_schedules.rb b/db/migrate/20160630052453_create_schedules.rb
deleted file mode 100644
index f1cf5fa5c5..0000000000
--- a/db/migrate/20160630052453_create_schedules.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class CreateSchedules < ActiveRecord::Migration
- def change
- create_table :schedules do |t|
- t.string :name, null: false
- t.timestamps
- end
- end
-end
diff --git a/db/migrate/20160630055825_create_order_cycle_schedules.rb b/db/migrate/20160630055825_create_order_cycle_schedules.rb
deleted file mode 100644
index 99147467c9..0000000000
--- a/db/migrate/20160630055825_create_order_cycle_schedules.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class CreateOrderCycleSchedules < ActiveRecord::Migration
- def change
- create_table :order_cycle_schedules do |t|
- t.references :order_cycle, null: false
- t.references :schedule, null: false
- end
-
- add_index :order_cycle_schedules, :order_cycle_id
- add_index :order_cycle_schedules, :schedule_id
-
- add_foreign_key :order_cycle_schedules, :order_cycles, name: 'oc_schedules_order_cycle_id_fk'
- add_foreign_key :order_cycle_schedules, :schedules, name: 'oc_schedules_schedule_id_fk'
- end
-end
diff --git a/db/migrate/20160707023818_drop_cms.rb b/db/migrate/20160707023818_drop_cms.rb
deleted file mode 100644
index 018b755466..0000000000
--- a/db/migrate/20160707023818_drop_cms.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-class DropCms < ActiveRecord::Migration
-
- # Reverse of CreateCms in 20121009232513_create_cms.rb, including foreign keys defined
- # in 20140402033428_add_foreign_keys.rb
-
- def up
- drop_table_cascade :cms_sites
- drop_table_cascade :cms_layouts
- drop_table_cascade :cms_pages
- drop_table_cascade :cms_snippets
- drop_table_cascade :cms_blocks
- drop_table_cascade :cms_files
- drop_table_cascade :cms_revisions
- drop_table_cascade :cms_categories
- drop_table_cascade :cms_categorizations
- end
-
- def down
- text_limit = case ActiveRecord::Base.connection.adapter_name
- when 'PostgreSQL'
- { }
- else
- { :limit => 16777215 }
- end
-
- # -- Sites --------------------------------------------------------------
- create_table :cms_sites do |t|
- t.string :label, :null => false
- t.string :identifier, :null => false
- t.string :hostname, :null => false
- t.string :path
- t.string :locale, :null => false, :default => 'en'
- t.boolean :is_mirrored, :null => false, :default => false
- end
- add_index :cms_sites, :hostname
- add_index :cms_sites, :is_mirrored
-
- # -- Layouts ------------------------------------------------------------
- create_table :cms_layouts do |t|
- t.integer :site_id, :null => false
- t.integer :parent_id
- t.string :app_layout
- t.string :label, :null => false
- t.string :identifier, :null => false
- t.text :content, text_limit
- t.text :css, text_limit
- t.text :js, text_limit
- t.integer :position, :null => false, :default => 0
- t.boolean :is_shared, :null => false, :default => false
- t.timestamps
- end
- add_index :cms_layouts, [:parent_id, :position]
- add_index :cms_layouts, [:site_id, :identifier], :unique => true
-
- # -- Pages --------------------------------------------------------------
- create_table :cms_pages do |t|
- t.integer :site_id, :null => false
- t.integer :layout_id
- t.integer :parent_id
- t.integer :target_page_id
- t.string :label, :null => false
- t.string :slug
- t.string :full_path, :null => false
- t.text :content, text_limit
- t.integer :position, :null => false, :default => 0
- t.integer :children_count, :null => false, :default => 0
- t.boolean :is_published, :null => false, :default => true
- t.boolean :is_shared, :null => false, :default => false
- t.timestamps
- end
- add_index :cms_pages, [:site_id, :full_path]
- add_index :cms_pages, [:parent_id, :position]
-
- # -- Page Blocks --------------------------------------------------------
- create_table :cms_blocks do |t|
- t.integer :page_id, :null => false
- t.string :identifier, :null => false
- t.text :content
- t.timestamps
- end
- add_index :cms_blocks, [:page_id, :identifier]
-
- # -- Snippets -----------------------------------------------------------
- create_table :cms_snippets do |t|
- t.integer :site_id, :null => false
- t.string :label, :null => false
- t.string :identifier, :null => false
- t.text :content, text_limit
- t.integer :position, :null => false, :default => 0
- t.boolean :is_shared, :null => false, :default => false
- t.timestamps
- end
- add_index :cms_snippets, [:site_id, :identifier], :unique => true
- add_index :cms_snippets, [:site_id, :position]
-
- # -- Files --------------------------------------------------------------
- create_table :cms_files do |t|
- t.integer :site_id, :null => false
- t.integer :block_id
- t.string :label, :null => false
- t.string :file_file_name, :null => false
- t.string :file_content_type, :null => false
- t.integer :file_file_size, :null => false
- t.string :description, :limit => 2048
- t.integer :position, :null => false, :default => 0
- t.timestamps
- end
- add_index :cms_files, [:site_id, :label]
- add_index :cms_files, [:site_id, :file_file_name]
- add_index :cms_files, [:site_id, :position]
- add_index :cms_files, [:site_id, :block_id]
-
- # -- Revisions -----------------------------------------------------------
- create_table :cms_revisions, :force => true do |t|
- t.string :record_type, :null => false
- t.integer :record_id, :null => false
- t.text :data, text_limit
- t.datetime :created_at
- end
- add_index :cms_revisions, [:record_type, :record_id, :created_at]
-
- # -- Categories ---------------------------------------------------------
- create_table :cms_categories, :force => true do |t|
- t.integer :site_id, :null => false
- t.string :label, :null => false
- t.string :categorized_type, :null => false
- end
- add_index :cms_categories, [:site_id, :categorized_type, :label], :unique => true
-
- create_table :cms_categorizations, :force => true do |t|
- t.integer :category_id, :null => false
- t.string :categorized_type, :null => false
- t.integer :categorized_id, :null => false
- end
- add_index :cms_categorizations, [:category_id, :categorized_type, :categorized_id], :unique => true,
- :name => 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id'
-
-
- # -- Foreign keys, from 20140402033428_add_foreign_keys.rb
- add_foreign_key "cms_blocks", "cms_pages", name: "cms_blocks_page_id_fk", column: "page_id"
- add_foreign_key "cms_categories", "cms_sites", name: "cms_categories_site_id_fk", column: "site_id", dependent: :delete
- add_foreign_key "cms_categorizations", "cms_categories", name: "cms_categorizations_category_id_fk", column: "category_id"
- add_foreign_key "cms_files", "cms_blocks", name: "cms_files_block_id_fk", column: "block_id"
- add_foreign_key "cms_files", "cms_sites", name: "cms_files_site_id_fk", column: "site_id"
- add_foreign_key "cms_layouts", "cms_layouts", name: "cms_layouts_parent_id_fk", column: "parent_id"
- add_foreign_key "cms_layouts", "cms_sites", name: "cms_layouts_site_id_fk", column: "site_id", dependent: :delete
- add_foreign_key "cms_pages", "cms_layouts", name: "cms_pages_layout_id_fk", column: "layout_id"
- add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_parent_id_fk", column: "parent_id"
- add_foreign_key "cms_pages", "cms_sites", name: "cms_pages_site_id_fk", column: "site_id", dependent: :delete
- add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_target_page_id_fk", column: "target_page_id"
- add_foreign_key "cms_snippets", "cms_sites", name: "cms_snippets_site_id_fk", column: "site_id", dependent: :delete
-
- end
-end
diff --git a/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb b/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb
deleted file mode 100644
index 306276bcc0..0000000000
--- a/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddBillAddressAndShipAddressToCustomer < ActiveRecord::Migration
- def change
- add_column :customers, :bill_address_id, :integer
- add_column :customers, :ship_address_id, :integer
-
- add_index :customers, :bill_address_id
- add_index :customers, :ship_address_id
-
- add_foreign_key :customers, :spree_addresses, column: :bill_address_id
- add_foreign_key :customers, :spree_addresses, column: :ship_address_id
- end
-end
diff --git a/db/migrate/20160713013358_add_name_to_customer.rb b/db/migrate/20160713013358_add_name_to_customer.rb
deleted file mode 100644
index 832816657e..0000000000
--- a/db/migrate/20160713013358_add_name_to_customer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddNameToCustomer < ActiveRecord::Migration
- def change
- add_column :customers, :name, :string
- end
-end
diff --git a/db/migrate/20160819045727_create_standing_orders.rb b/db/migrate/20160819045727_create_standing_orders.rb
deleted file mode 100644
index 661bf7411b..0000000000
--- a/db/migrate/20160819045727_create_standing_orders.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-class CreateStandingOrders < ActiveRecord::Migration
- def change
- create_table :standing_orders do |t|
- t.references :shop, null: false
- t.references :customer, null: false
- t.references :schedule, null: false
- t.references :payment_method, null: false
- t.references :shipping_method, null: false
- t.datetime :begins_at, :ends_at
- t.timestamps
- end
-
- add_index :standing_orders, :shop_id
- add_index :standing_orders, :customer_id
- add_index :standing_orders, :schedule_id
- add_index :standing_orders, :payment_method_id
- add_index :standing_orders, :shipping_method_id
-
- add_foreign_key :standing_orders, :enterprises, name: 'oc_standing_orders_shop_id_fk', column: :shop_id
- add_foreign_key :standing_orders, :customers, name: 'oc_standing_orders_customer_id_fk'
- add_foreign_key :standing_orders, :schedules, name: 'oc_standing_orders_schedule_id_fk'
- add_foreign_key :standing_orders, :spree_payment_methods, name: 'oc_standing_orders_payment_method_id_fk', column: :payment_method_id
- add_foreign_key :standing_orders, :spree_shipping_methods, name: 'oc_standing_orders_shipping_method_id_fk', column: :shipping_method_id
- end
-end
diff --git a/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb b/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb
deleted file mode 100644
index eb8e206e8f..0000000000
--- a/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-class SwapCalculatorToFlatPercentPerItem < ActiveRecord::Migration
- class Spree::Calculator < ActiveRecord::Base
- end
-
- def up
- Spree::Calculator.where(calculable_type: "EnterpriseFee", type: 'Spree::Calculator::FlatPercentItemTotal').each do |c|
- swap_calculator_type c, 'Calculator::FlatPercentPerItem'
- end
- end
-
- def down
- Spree::Calculator.where(calculable_type: "EnterpriseFee", type: 'Spree::Calculator::FlatPercentPerItem').each do |c|
- swap_calculator_type c, 'Calculator::FlatPercentItemTotal'
- end
- end
-
-
- private
-
- def swap_calculator_type(calculator, to_class)
- value = calculator.preferred_flat_percent
-
- calculator.type = to_class
- calculator.save
-
- calculator = Spree::Calculator.find calculator.id
- calculator.preferred_flat_percent = value
- end
-end
diff --git a/db/migrate/20160824013751_create_standing_line_items.rb b/db/migrate/20160824013751_create_standing_line_items.rb
deleted file mode 100644
index 90a0d46af3..0000000000
--- a/db/migrate/20160824013751_create_standing_line_items.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class CreateStandingLineItems < ActiveRecord::Migration
- def change
- create_table :standing_line_items do |t|
- t.references :standing_order, null: false
- t.references :variant, null: false
- t.integer :quantity, null: false
- t.timestamps
- end
-
- add_index :standing_line_items, :standing_order_id
- add_index :standing_line_items, :variant_id
-
- add_foreign_key :standing_line_items, :standing_orders, name: 'oc_standing_line_items_standing_order_id_fk'
- add_foreign_key :standing_line_items, :spree_variants, name: 'oc_standing_line_items_variant_id_fk', column: :variant_id
- end
-end
diff --git a/db/migrate/20160828115018_create_stripe_accounts.rb b/db/migrate/20160828115018_create_stripe_accounts.rb
deleted file mode 100644
index 56ab206540..0000000000
--- a/db/migrate/20160828115018_create_stripe_accounts.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateStripeAccounts < ActiveRecord::Migration
- def change
- create_table :stripe_accounts do |t|
- t.string :stripe_user_id
- t.string :stripe_publishable_key
- t.timestamps
- t.belongs_to :enterprise
- end
-
- add_index :stripe_accounts, :enterprise_id, unique: true
- end
-end
diff --git a/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb b/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb
deleted file mode 100644
index a4224678df..0000000000
--- a/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# This migration comes from spree (originally 20121213162028)
-class AddStateToSpreeAdjustments < ActiveRecord::Migration
- def change
- add_column :spree_adjustments, :state, :string
- remove_column :spree_adjustments, :locked
- end
-end
diff --git a/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb b/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb
deleted file mode 100644
index 7e92c7e74c..0000000000
--- a/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAllowGuestOrdersToEnterprise < ActiveRecord::Migration
- def change
- add_column :enterprises, :allow_guest_orders, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb b/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb
deleted file mode 100644
index 887ce44058..0000000000
--- a/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddAllowOrderChangesToEnterprise < ActiveRecord::Migration
- def change
- add_column :enterprises, :allow_order_changes, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb b/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb
deleted file mode 100644
index 259227be5f..0000000000
--- a/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddShipAndBillAddressToStandingOrders < ActiveRecord::Migration
- def change
- add_column :standing_orders, :bill_address_id, :integer, null: false
- add_column :standing_orders, :ship_address_id, :integer, null: false
-
- add_index :standing_orders, :bill_address_id
- add_index :standing_orders, :ship_address_id
-
- add_foreign_key :standing_orders, :spree_addresses, column: :bill_address_id
- add_foreign_key :standing_orders, :spree_addresses, column: :ship_address_id
- end
-end
diff --git a/db/migrate/20161020012017_create_standing_order_orders.rb b/db/migrate/20161020012017_create_standing_order_orders.rb
deleted file mode 100644
index cbaa0c14cc..0000000000
--- a/db/migrate/20161020012017_create_standing_order_orders.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class CreateStandingOrderOrders < ActiveRecord::Migration
- def change
- create_table :standing_order_orders do |t|
- t.references :standing_order, null: false
- t.references :order, null: false
- t.datetime :cancelled_at
- t.timestamps
- end
-
- add_index :standing_order_orders, :standing_order_id
- add_index :standing_order_orders, :order_id, unique: true
-
- add_foreign_key "standing_order_orders", "standing_orders", name: "standing_order_id_fk", column: "standing_order_id"
- add_foreign_key "standing_order_orders", "spree_orders", name: "order_id_fk", column: "order_id"
- end
-end
diff --git a/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb b/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb
deleted file mode 100644
index 9becae9930..0000000000
--- a/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddStandingOrdersPlacedAtToOrderCycles < ActiveRecord::Migration
- def change
- add_column :order_cycles, :standing_orders_placed_at, :datetime
- end
-end
diff --git a/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb b/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb
deleted file mode 100644
index 967a24b838..0000000000
--- a/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddPriceEstimateToStandingLineItems < ActiveRecord::Migration
- def change
- add_column :standing_line_items, :price_estimate, :decimal, :precision => 8, :scale => 2
- end
-end
diff --git a/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb b/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb
deleted file mode 100644
index f004e28557..0000000000
--- a/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddCanceledAtToStandingOrders < ActiveRecord::Migration
- def change
- add_column :standing_orders, :canceled_at, :datetime
- end
-end
diff --git a/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb b/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb
deleted file mode 100644
index 6d2c3d0c3f..0000000000
--- a/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class RenameStandingOrderOrdersCancelledAt < ActiveRecord::Migration
- def change
- # No, I'm not illiterate. I just want to maintain consistency with
- # existing Spree column names that are spelt using US English
- rename_column :standing_order_orders, :cancelled_at, :canceled_at
- end
-end
diff --git a/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb b/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb
deleted file mode 100644
index e6e6e95852..0000000000
--- a/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddPausedAtToStandingOrders < ActiveRecord::Migration
- def change
- add_column :standing_orders, :paused_at, :datetime
- end
-end
diff --git a/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb b/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb
deleted file mode 100644
index 3f4bb3c378..0000000000
--- a/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddStandingOrdersConfirmedAtToOrderCycles < ActiveRecord::Migration
- def change
- add_column :order_cycles, :standing_orders_confirmed_at, :datetime
- end
-end
diff --git a/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb b/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb
deleted file mode 100644
index 964037f823..0000000000
--- a/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RenameStandingOrderOrdersToProxyOrders < ActiveRecord::Migration
- def change
- remove_index :standing_order_orders, :order_id
- remove_index :standing_order_orders, :standing_order_id
- rename_table :standing_order_orders, :proxy_orders
- add_index :proxy_orders, :order_id, unique: true
- add_index :proxy_orders, :standing_order_id
- end
-end
diff --git a/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb b/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb
deleted file mode 100644
index fd18937ea0..0000000000
--- a/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class AddOrderCycleIdToProxyOrders < ActiveRecord::Migration
- def up
- add_column :proxy_orders, :order_cycle_id, :integer
-
- ProxyOrder.find_each do |proxy_order|
- order_cycle_id = proxy_order.order.order_cycle_id
- proxy_order.update_attribute(:order_cycle_id, order_cycle_id)
- end
-
- change_column :proxy_orders, :order_cycle_id, :integer, null: false
- add_index :proxy_orders, [:order_cycle_id, :standing_order_id], unique: true
- add_foreign_key :proxy_orders, :order_cycles
- end
-
- def down
- remove_foreign_key :proxy_orders, :order_cycles
- remove_index :proxy_orders, :order_cycle_id
- remove_column :proxy_orders, :order_cycle_id
- end
-end
diff --git a/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb b/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb
deleted file mode 100644
index 726dde623a..0000000000
--- a/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RemoveProxyOrderOrderNotNullConstraint < ActiveRecord::Migration
- def up
- change_column :proxy_orders, :order_id, :integer, null: true
- end
-
- def down
- change_column :proxy_orders, :order_id, :integer, null: false
- end
-end
diff --git a/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb b/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb
deleted file mode 100644
index 3bd4ad13cb..0000000000
--- a/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddEnableStandingOrdersToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :enable_standing_orders, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb b/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb
deleted file mode 100644
index d9cfca91ba..0000000000
--- a/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddInvoiceTextAndInvoiceLogoToEnterprises < ActiveRecord::Migration
- def change
- add_column :enterprises, :invoice_text, :text
- add_column :enterprises, :display_invoice_logo, :boolean, default: false
- end
-end
diff --git a/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb b/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb
deleted file mode 100644
index daf67b1211..0000000000
--- a/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddPlacedAtAndConfirmedAtToProxyOrders < ActiveRecord::Migration
- def change
- add_column :proxy_orders, :placed_at, :datetime
- add_column :proxy_orders, :confirmed_at, :datetime
- end
-end
diff --git a/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb b/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb
deleted file mode 100644
index 29e50e0c1a..0000000000
--- a/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class AddUserIdToSpreeCreditCards < ActiveRecord::Migration
- def change
- unless Spree::CreditCard.column_names.include? "user_id"
- add_column :spree_credit_cards, :user_id, :integer
- add_index :spree_credit_cards, :user_id
- end
- end
-end
diff --git a/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb b/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb
deleted file mode 100644
index 76c1cab805..0000000000
--- a/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class AddPaymentMethodToSpreeCreditCards < ActiveRecord::Migration
- def change
- unless Spree::CreditCard.column_names.include? "payment_method_id"
- add_column :spree_credit_cards, :payment_method_id, :integer
- add_index :spree_credit_cards, :payment_method_id
- end
- end
-end
diff --git a/db/migrate/20170310231746_add_import_date_to_spree_variants.rb b/db/migrate/20170310231746_add_import_date_to_spree_variants.rb
deleted file mode 100644
index d5acbf882e..0000000000
--- a/db/migrate/20170310231746_add_import_date_to_spree_variants.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddImportDateToSpreeVariants < ActiveRecord::Migration
- def change
- add_column :spree_variants, :import_date, :datetime
- end
-end
diff --git a/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb b/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb
deleted file mode 100644
index daef32ec61..0000000000
--- a/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddImportDateToVariantOverrides < ActiveRecord::Migration
- def change
- add_column :variant_overrides, :import_date, :datetime
- end
-end
diff --git a/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb b/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb
deleted file mode 100644
index 2c426824d8..0000000000
--- a/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# This migration comes from spree_paypal_express (originally 20140117051315)
-class RenamePaymentMethods < ActiveRecord::Migration
- def up
- execute <<-SQL
- update spree_payment_methods set type = 'Spree::Gateway::PayPalExpress' WHERE type = 'Spree::BillingIntegration::PaypalExpress'
- SQL
- end
-
- def down
- execute <<-SQL
- update spree_payment_methods set type = 'Spree::BillingIntegration::PaypalExpress' WHERE type = 'Spree::Gateway::PayPalExpress'
- SQL
- end
-end
diff --git a/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb b/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb
deleted file mode 100644
index 28a9807184..0000000000
--- a/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130301205200)
-class AddTrackingUrlToSpreeShippingMethods < ActiveRecord::Migration
- def change
- add_column :spree_shipping_methods, :tracking_url, :string
- end
-end
diff --git a/db/migrate/20170512115519_add_locale_to_spree_users.rb b/db/migrate/20170512115519_add_locale_to_spree_users.rb
deleted file mode 100644
index f694bff1f7..0000000000
--- a/db/migrate/20170512115519_add_locale_to_spree_users.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddLocaleToSpreeUsers < ActiveRecord::Migration
- def change
- add_column :spree_users, :locale, :string, limit: 5
- end
-end
diff --git a/db/migrate/20170710145821_add_confirmable_to_user.rb b/db/migrate/20170710145821_add_confirmable_to_user.rb
deleted file mode 100644
index cd458545e0..0000000000
--- a/db/migrate/20170710145821_add_confirmable_to_user.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class AddConfirmableToUser < ActiveRecord::Migration
- def up
- add_column :spree_users, :confirmation_token, :string
- add_column :spree_users, :confirmed_at, :datetime
- add_column :spree_users, :confirmation_sent_at, :datetime
- add_column :spree_users, :unconfirmed_email, :string
- add_index :spree_users, :confirmation_token, :unique => true
-
- # Set all current users to confirmed
- Spree::User.update_all(confirmed_at: Time.zone.now)
- end
-
- def down
- remove_columns :spree_users, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email
- end
-end
diff --git a/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb b/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb
deleted file mode 100644
index a4aad51dd4..0000000000
--- a/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class RemoveConfirmableFromEnterprises < ActiveRecord::Migration
- def up
- remove_columns :enterprises, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email
- end
-
- def down
- add_column :enterprises, :confirmation_token, :string
- add_column :enterprises, :confirmed_at, :datetime
- add_column :enterprises, :confirmation_sent_at, :datetime
- add_column :enterprises, :unconfirmed_email, :string
- add_index :enterprises, :confirmation_token, :unique => true
-
- # Existing enterprises are assumed to be confirmed
- Enterprise.update_all(:confirmed_at => Time.zone.now)
- end
-end
diff --git a/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb b/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb
deleted file mode 100644
index 128cc2a554..0000000000
--- a/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddReceivesNotificationsToEnterpriseRoles < ActiveRecord::Migration
- def change
- add_column :enterprise_roles, :receives_notifications, :boolean, default: false
- end
-end
diff --git a/db/migrate/20170728140134_remove_email_from_enterprises.rb b/db/migrate/20170728140134_remove_email_from_enterprises.rb
deleted file mode 100644
index b5cd8420c0..0000000000
--- a/db/migrate/20170728140134_remove_email_from_enterprises.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-class RemoveEmailFromEnterprises < ActiveRecord::Migration
- class Enterprise < ActiveRecord::Base; end
- class Spree::User < ActiveRecord::Base; end
-
- class EnterpriseRole < ActiveRecord::Base
- belongs_to :user, class_name: 'Spree::User'
- belongs_to :enterprise, class_name: 'Enterprise'
- end
-
- def up
- Enterprise.reset_column_information
- Spree::User.reset_column_information
- EnterpriseRole.reset_column_information
-
- Enterprise.select([:id, :email, :owner_id]).each do |enterprise|
- update_enterprise_contact enterprise
- end
-
- remove_column :enterprises, :email
- rename_column :enterprises, :contact, :contact_name
- end
-
- def down
- Enterprise.reset_column_information
- Spree::User.reset_column_information
- EnterpriseRole.reset_column_information
-
- add_column :enterprises, :email, :string
- rename_column :enterprises, :contact_name, :contact
-
- Enterprise.select(:id).each do |e|
- manager = EnterpriseRole.find_by(enterprise_id: e.id, receives_notifications: true)
- user = Spree::User.find(manager.user_id)
- e.update_attribute :email, user.email
- end
- end
-
- def update_enterprise_contact(enterprise)
- contact_user = contact_or_owner(enterprise)
-
- role = EnterpriseRole.find_or_initialize_by(user_id: contact_user.id, enterprise_id: enterprise.id)
- role.update_attribute :receives_notifications, true
- end
-
- def contact_or_owner(enterprise)
- Spree::User.find_by(email: enterprise.email) || Spree::User.find(enterprise.owner_id)
- end
-end
diff --git a/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb b/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb
deleted file mode 100644
index 2db2182d9c..0000000000
--- a/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class ChangeDefaultValueOfSpreeUsersEnterpriseLimit < ActiveRecord::Migration
- def up
- change_column :spree_users, :enterprise_limit, :integer, default: 5
- end
-
- def down
- change_column :spree_users, :enterprise_limit, :integer, default: 1
- end
-end
diff --git a/db/migrate/20170921065259_update_adjustment_states.spree.rb b/db/migrate/20170921065259_update_adjustment_states.spree.rb
deleted file mode 100644
index 9040709751..0000000000
--- a/db/migrate/20170921065259_update_adjustment_states.spree.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# This migration comes from spree (originally 20130417120035)
-class UpdateAdjustmentStates < ActiveRecord::Migration
- def up
- Spree::Order.complete.find_each do |order|
- order.adjustments.update_all(:state => 'closed')
- end
-
- Spree::Shipment.shipped.includes(:adjustment).find_each do |shipment|
- shipment.adjustment.update_column(:state, 'finalized') if shipment.adjustment
- end
-
- Spree::Adjustment.where(:state => nil).update_all(:state => 'open')
- end
-
- def down
- end
-end
diff --git a/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb b/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb
deleted file mode 100644
index 60e5133a72..0000000000
--- a/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class AddCreditCardToStandingOrders < ActiveRecord::Migration
- def change
- add_column :standing_orders, :credit_card_id, :integer
- add_index :standing_orders, :credit_card_id
- add_foreign_key :standing_orders, :spree_credit_cards, name: :standing_orders_credit_card_id_fk, column: :credit_card_id
- end
-end
diff --git a/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb b/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb
deleted file mode 100644
index 91c90d90b5..0000000000
--- a/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-class RenameStandingOrdersToSubscriptions < ActiveRecord::Migration
- def up
- remove_foreign_key :proxy_orders, name: :standing_order_id_fk
- remove_foreign_key :standing_line_items, name: :oc_standing_line_items_standing_order_id_fk
-
- remove_foreign_key :standing_orders, name: :oc_standing_orders_customer_id_fk
- remove_foreign_key :standing_orders, name: :oc_standing_orders_shop_id_fk
- remove_foreign_key :standing_orders, name: :oc_standing_orders_schedule_id_fk
- remove_foreign_key :standing_orders, name: :standing_orders_bill_address_id_fk
- remove_foreign_key :standing_orders, name: :standing_orders_ship_address_id_fk
- remove_foreign_key :standing_orders, name: :standing_orders_credit_card_id_fk
- remove_foreign_key :standing_orders, name: :oc_standing_orders_payment_method_id_fk
- remove_foreign_key :standing_orders, name: :oc_standing_orders_shipping_method_id_fk
-
- remove_index :proxy_orders, :column => [:order_cycle_id, :standing_order_id]
- remove_index :proxy_orders, :column => [:standing_order_id]
- remove_index :standing_line_items, :column => [:standing_order_id]
-
- rename_table :standing_orders, :subscriptions
-
- rename_index :subscriptions, :index_standing_orders_on_bill_address_id, :index_subscriptions_on_bill_address_id
- rename_index :subscriptions, :index_standing_orders_on_credit_card_id, :index_subscriptions_on_credit_card_id
- rename_index :subscriptions, :index_standing_orders_on_customer_id, :index_subscriptions_on_customer_id
- rename_index :subscriptions, :index_standing_orders_on_payment_method_id, :index_subscriptions_on_payment_method_id
- rename_index :subscriptions, :index_standing_orders_on_schedule_id, :index_subscriptions_on_schedule_id
- rename_index :subscriptions, :index_standing_orders_on_ship_address_id, :index_subscriptions_on_ship_address_id
- rename_index :subscriptions, :index_standing_orders_on_shipping_method_id, :index_subscriptions_on_shipping_method_id
- rename_index :subscriptions, :index_standing_orders_on_shop_id, :index_subscriptions_on_shop_id
-
- rename_column :enterprises, :enable_standing_orders, :enable_subscriptions
- rename_column :proxy_orders, :standing_order_id, :subscription_id
- rename_column :standing_line_items, :standing_order_id, :subscription_id
-
- add_index :proxy_orders, [:order_cycle_id, :subscription_id], unique: true
- add_index :proxy_orders, :subscription_id
- add_index :standing_line_items, :subscription_id
-
- add_foreign_key :proxy_orders, :subscriptions, name: :proxy_orders_subscription_id_fk
- add_foreign_key :standing_line_items, :subscriptions, name: :standing_line_items_subscription_id_fk
-
- add_foreign_key :subscriptions, :customers, name: :subscriptions_customer_id_fk
- add_foreign_key :subscriptions, :enterprises, name: :subscriptions_shop_id_fk, column: :shop_id
- add_foreign_key :subscriptions, :schedules, name: :subscriptions_schedule_id_fk
- add_foreign_key :subscriptions, :spree_addresses, name: :subscriptions_bill_address_id_fk, column: :bill_address_id
- add_foreign_key :subscriptions, :spree_addresses, name: :subscriptions_ship_address_id_fk, column: :ship_address_id
- add_foreign_key :subscriptions, :spree_credit_cards, name: :subscriptions_credit_card_id_fk, column: :credit_card_id
- add_foreign_key :subscriptions, :spree_payment_methods, name: :subscriptions_payment_method_id_fk, column: :payment_method_id
- add_foreign_key :subscriptions, :spree_shipping_methods, name: :subscriptions_shipping_method_id_fk, column: :shipping_method_id
- end
-
- def down
- remove_foreign_key :proxy_orders, name: :proxy_orders_subscription_id_fk
- remove_foreign_key :standing_line_items, name: :standing_line_items_subscription_id_fk
-
- remove_foreign_key :subscriptions, name: :subscriptions_customer_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_shop_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_schedule_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_bill_address_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_ship_address_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_credit_card_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_payment_method_id_fk
- remove_foreign_key :subscriptions, name: :subscriptions_shipping_method_id_fk
-
- remove_index :proxy_orders, :column => [:order_cycle_id, :subscription_id]
- remove_index :proxy_orders, :column => [:subscription_id]
- remove_index :standing_line_items, :column => [:subscription_id]
-
- rename_table :subscriptions, :standing_orders
-
- rename_index :standing_orders, :index_subscriptions_on_bill_address_id, :index_standing_orders_on_bill_address_id
- rename_index :standing_orders, :index_subscriptions_on_credit_card_id, :index_standing_orders_on_credit_card_id
- rename_index :standing_orders, :index_subscriptions_on_customer_id, :index_standing_orders_on_customer_id
- rename_index :standing_orders, :index_subscriptions_on_payment_method_id, :index_standing_orders_on_payment_method_id
- rename_index :standing_orders, :index_subscriptions_on_schedule_id, :index_standing_orders_on_schedule_id
- rename_index :standing_orders, :index_subscriptions_on_ship_address_id, :index_standing_orders_on_ship_address_id
- rename_index :standing_orders, :index_subscriptions_on_shipping_method_id, :index_standing_orders_on_shipping_method_id
- rename_index :standing_orders, :index_subscriptions_on_shop_id, :index_standing_orders_on_shop_id
-
- rename_column :enterprises, :enable_subscriptions, :enable_standing_orders
- rename_column :proxy_orders, :subscription_id, :standing_order_id
- rename_column :standing_line_items, :subscription_id, :standing_order_id
-
- add_index :proxy_orders, [:order_cycle_id, :standing_order_id], unique: true
- add_index :proxy_orders, :standing_order_id
- add_index :standing_line_items, :standing_order_id
-
- add_foreign_key :proxy_orders, :standing_orders, name: :standing_order_id_fk
- add_foreign_key :standing_line_items, :standing_orders, name: :oc_standing_line_items_standing_order_id_fk
-
- add_foreign_key :standing_orders, :customers, name: :oc_standing_orders_customer_id_fk
- add_foreign_key :standing_orders, :enterprises, name: :oc_standing_orders_shop_id_fk, column: :shop_id
- add_foreign_key :standing_orders, :schedules, name: :oc_standing_orders_schedule_id_fk
- add_foreign_key :standing_orders, :spree_addresses, name: :standing_orders_bill_address_id_fk, column: :bill_address_id
- add_foreign_key :standing_orders, :spree_addresses, name: :standing_orders_ship_address_id_fk, column: :ship_address_id
- add_foreign_key :standing_orders, :spree_credit_cards, name: :standing_orders_credit_card_id_fk, column: :credit_card_id
- add_foreign_key :standing_orders, :spree_payment_methods, name: :oc_standing_orders_payment_method_id_fk, column: :payment_method_id
- add_foreign_key :standing_orders, :spree_shipping_methods, name: :oc_standing_orders_shipping_method_id_fk, column: :shipping_method_id
- end
-end
diff --git a/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb b/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb
deleted file mode 100644
index eda85f905b..0000000000
--- a/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-class RenameStandingLineItemsToSubscriptionLineItems < ActiveRecord::Migration
- def up
- remove_foreign_key :standing_line_items, name: :oc_standing_line_items_variant_id_fk
- remove_foreign_key :standing_line_items, name: :standing_line_items_subscription_id_fk
-
- rename_table :standing_line_items, :subscription_line_items
-
- rename_index :subscription_line_items, :index_standing_line_items_on_subscription_id, :index_subscription_line_items_on_subscription_id
- rename_index :subscription_line_items, :index_standing_line_items_on_variant_id, :index_subscription_line_items_on_variant_id
-
- add_foreign_key :subscription_line_items, :spree_variants, name: :subscription_line_items_variant_id_fk, column: :variant_id
- add_foreign_key :subscription_line_items, :subscriptions, name: :subscription_line_items_subscription_id_fk
- end
-
- def down
- remove_foreign_key :subscription_line_items, name: :subscription_line_items_variant_id_fk
- remove_foreign_key :subscription_line_items, name: :subscription_line_items_subscription_id_fk
-
- rename_table :subscription_line_items, :standing_line_items
-
- rename_index :standing_line_items, :index_subscription_line_items_on_subscription_id, :index_standing_line_items_on_subscription_id
- rename_index :standing_line_items, :index_subscription_line_items_on_variant_id, :index_standing_line_items_on_variant_id
-
- add_foreign_key :standing_line_items, :spree_variants, name: :oc_standing_line_items_variant_id_fk, column: :variant_id
- add_foreign_key :standing_line_items, :subscriptions, name: :standing_line_items_subscription_id_fk
- end
-end
diff --git a/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb b/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb
deleted file mode 100644
index 2c4f29d891..0000000000
--- a/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class AddShippingFeeEstimateAndPaymentFeeEstimateToSubscription < ActiveRecord::Migration
- def change
- add_column :subscriptions, :shipping_fee_estimate, :decimal, :precision => 8, :scale => 2
- add_column :subscriptions, :payment_fee_estimate, :decimal, :precision => 8, :scale => 2
- end
-end
diff --git a/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb b/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb
deleted file mode 100644
index b41d698eb3..0000000000
--- a/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class RemovePlacedAtAndConfirmedAtFromOrderCycles < ActiveRecord::Migration
- def up
- remove_column :order_cycles, :standing_orders_placed_at
- remove_column :order_cycles, :standing_orders_confirmed_at
- end
-
- def down
- add_column :order_cycles, :standing_orders_placed_at, :datetime
- add_column :order_cycles, :standing_orders_confirmed_at, :datetime
- end
-end
diff --git a/db/migrate/20180406045821_add_charges_allowed_to_customers.rb b/db/migrate/20180406045821_add_charges_allowed_to_customers.rb
deleted file mode 100644
index 4503dc87b6..0000000000
--- a/db/migrate/20180406045821_add_charges_allowed_to_customers.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddChargesAllowedToCustomers < ActiveRecord::Migration
- def change
- add_column :customers, :allow_charges, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20180418025217_add_is_default_to_credit_card.rb b/db/migrate/20180418025217_add_is_default_to_credit_card.rb
deleted file mode 100644
index c39b3e44dc..0000000000
--- a/db/migrate/20180418025217_add_is_default_to_credit_card.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddIsDefaultToCreditCard < ActiveRecord::Migration
- def change
- add_column :spree_credit_cards, :is_default, :boolean, default: false
- end
-end
diff --git a/db/migrate/20180426145630_create_spree_stock_items.spree.rb b/db/migrate/20180426145630_create_spree_stock_items.spree.rb
deleted file mode 100644
index cd6f349740..0000000000
--- a/db/migrate/20180426145630_create_spree_stock_items.spree.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# This migration comes from spree (originally 20130211190146)
-class CreateSpreeStockItems < ActiveRecord::Migration
- def change
- create_table :spree_stock_items do |t|
- t.belongs_to :stock_location
- t.belongs_to :variant
- t.integer :count_on_hand, null: false, default: 0
- t.integer :lock_version
-
- t.timestamps
- end
- add_index :spree_stock_items, :stock_location_id
- add_index :spree_stock_items, [:stock_location_id, :variant_id], :name => 'stock_item_by_loc_and_var_id'
- end
-end
diff --git a/db/migrate/20180426145631_create_spree_stock_locations.spree.rb b/db/migrate/20180426145631_create_spree_stock_locations.spree.rb
deleted file mode 100644
index a3e4d1a4dc..0000000000
--- a/db/migrate/20180426145631_create_spree_stock_locations.spree.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# This migration comes from spree (originally 20130211191120)
-class CreateSpreeStockLocations < ActiveRecord::Migration
- def change
- create_table :spree_stock_locations do |t|
- t.string :name
- t.belongs_to :address
-
- t.timestamps
- end
- add_index :spree_stock_locations, :address_id
- end
-end
diff --git a/db/migrate/20180426145632_create_default_stock.spree.rb b/db/migrate/20180426145632_create_default_stock.spree.rb
deleted file mode 100644
index 7e1d188e4a..0000000000
--- a/db/migrate/20180426145632_create_default_stock.spree.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-Spree::Stock::Quantifier.class_eval do
- def initialize(variant)
- @variant = variant
- @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant)
- end
-end
-
-# This migration comes from spree (originally 20130213191427)
-class CreateDefaultStock < ActiveRecord::Migration
- def up
- Spree::StockLocation.skip_callback(:create, :after, :create_stock_items)
- Spree::StockItem.skip_callback(:save, :after, :process_backorders)
- location = Spree::StockLocation.create(name: 'default')
- Spree::Variant.all.each do |variant|
- stock_item = location.stock_items.build(variant: variant)
- stock_item.send(:count_on_hand=, variant.count_on_hand)
- stock_item.save!
- end
-
- remove_column :spree_variants, :count_on_hand
- end
-
- def down
- add_column :spree_variants, :count_on_hand, :integer
-
- Spree::StockItem.all.each do |stock_item|
- stock_item.variant.update_column :count_on_hand, stock_item.count_on_hand
- end
-
- Spree::StockLocation.delete_all
- Spree::StockItem.delete_all
- end
-end
-
diff --git a/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb b/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb
deleted file mode 100644
index e102d7febb..0000000000
--- a/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130226191231)
-class AddStockLocationIdToSpreeShipments < ActiveRecord::Migration
- def change
- add_column :spree_shipments, :stock_location_id, :integer
- end
-end
diff --git a/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb b/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb
deleted file mode 100644
index c3879d3604..0000000000
--- a/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# This migration comes from spree (originally 20130227143905)
-class AddPendingToInventoryUnit < ActiveRecord::Migration
- def change
- add_column :spree_inventory_units, :pending, :boolean, :default => true
- Spree::InventoryUnit.update_all(:pending => false)
- end
-end
diff --git a/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb b/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb
deleted file mode 100644
index 0732d4ffd0..0000000000
--- a/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# This migration comes from spree (originally 20130228164411)
-class RemoveOnDemandFromProductAndVariant < ActiveRecord::Migration
- def change
- remove_column :spree_products, :on_demand
- # we are removing spree_variants.on_demand in a later migration
- end
-end
diff --git a/db/migrate/20180426145636_create_shipping_method_zone.spree.rb b/db/migrate/20180426145636_create_shipping_method_zone.spree.rb
deleted file mode 100644
index 2d99447b13..0000000000
--- a/db/migrate/20180426145636_create_shipping_method_zone.spree.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# This migration comes from spree (originally 20130228210442)
-class CreateShippingMethodZone < ActiveRecord::Migration
- def up
- create_table :shipping_methods_zones, :id => false do |t|
- t.integer :shipping_method_id
- t.integer :zone_id
- end
- # This association has been corrected in a latter migration
- # but when this database migration runs, the table is still incorrectly named
- # 'shipping_methods_zones' instead of 'spre_shipping_methods_zones'
- Spree::ShippingMethod.has_and_belongs_to_many :zones, :join_table => 'shipping_methods_zones',
- :class_name => 'Spree::Zone',
- :foreign_key => 'shipping_method_id'
- Spree::ShippingMethod.all.each{|sm| sm.zones << Spree::Zone.find(sm.zone_id)}
-
- remove_column :spree_shipping_methods, :zone_id
- end
-
- def down
- drop_table :shipping_methods_zones
- add_column :spree_shipping_methods, :zone_id, :integer
- end
-end
diff --git a/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb b/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb
deleted file mode 100644
index f686ac4aa7..0000000000
--- a/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130301162745)
-class RemoveShippingCategoryIdFromShippingMethod < ActiveRecord::Migration
- def change
- remove_column :spree_shipping_methods, :shipping_category_id
- end
-end
diff --git a/db/migrate/20180426145638_create_shipping_method_categories.spree.rb b/db/migrate/20180426145638_create_shipping_method_categories.spree.rb
deleted file mode 100644
index 2af03a7ec0..0000000000
--- a/db/migrate/20180426145638_create_shipping_method_categories.spree.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# This migration comes from spree (originally 20130301162924)
-class CreateShippingMethodCategories < ActiveRecord::Migration
- def change
- create_table :spree_shipping_method_categories do |t|
- t.integer :shipping_method_id, :null => false
- t.integer :shipping_category_id, :null => false
-
- t.timestamps
- end
-
- add_index :spree_shipping_method_categories, :shipping_method_id
- add_index :spree_shipping_method_categories, :shipping_category_id
- end
-end
diff --git a/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb b/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb
deleted file mode 100644
index f2932a57b3..0000000000
--- a/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# This migration comes from spree (originally 20130304162240)
-class CreateSpreeShippingRates < ActiveRecord::Migration
- def up
- create_table :spree_shipping_rates do |t|
- t.belongs_to :shipment
- t.belongs_to :shipping_method
- t.boolean :selected, :default => false
- t.decimal :cost, :precision => 8, :scale => 2
- t.timestamps
- end
- add_index(:spree_shipping_rates, [:shipment_id, :shipping_method_id],
- :name => 'spree_shipping_rates_join_index',
- :unique => true)
-
- # Spree::Shipment.all.each do |shipment|
- # shipping_method = Spree::ShippingMethod.find(shipment.shipment_method_id)
- # shipment.add_shipping_method(shipping_method, true)
- # end
- end
-
- def down
- # add_column :spree_shipments, :shipping_method_id, :integer
- drop_table :spree_shipping_rates
- end
-end
diff --git a/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb b/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb
deleted file mode 100644
index 1562aecdb2..0000000000
--- a/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# This migration comes from spree (originally 20130304192936)
-class RemoveCategoryMatchAttributesFromShippingMethod < ActiveRecord::Migration
- def change
- remove_column :spree_shipping_methods, :match_none
- remove_column :spree_shipping_methods, :match_one
- remove_column :spree_shipping_methods, :match_all
- end
-end
diff --git a/db/migrate/20180426145641_create_stock_movements.spree.rb b/db/migrate/20180426145641_create_stock_movements.spree.rb
deleted file mode 100644
index d7c8cb88d3..0000000000
--- a/db/migrate/20180426145641_create_stock_movements.spree.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# This migration comes from spree (originally 20130305143310)
-class CreateStockMovements < ActiveRecord::Migration
- def change
- create_table :spree_stock_movements do |t|
- t.belongs_to :stock_item
- t.integer :quantity
- t.string :action
-
- t.timestamps
- end
- add_index :spree_stock_movements, :stock_item_id
- end
-end
diff --git a/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb b/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb
deleted file mode 100644
index 4a16efeb40..0000000000
--- a/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# This migration comes from spree (originally 20130306181701)
-class AddAddressFieldsToStockLocation < ActiveRecord::Migration
- def change
- remove_column :spree_stock_locations, :address_id
-
- add_column :spree_stock_locations, :address1, :string
- add_column :spree_stock_locations, :address2, :string
- add_column :spree_stock_locations, :city, :string
- add_column :spree_stock_locations, :state_id, :integer
- add_column :spree_stock_locations, :state_name, :string
- add_column :spree_stock_locations, :country_id, :integer
- add_column :spree_stock_locations, :zipcode, :string
- add_column :spree_stock_locations, :phone, :string
-
-
- usa = Spree::Country.where(:iso => 'US').first
- # In case USA isn't found.
- # See #3115
- country = usa || Spree::Country.first
- Spree::Country.reset_column_information
- Spree::StockLocation.update_all(:country_id => country)
- end
-end
diff --git a/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb b/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb
deleted file mode 100644
index 0e69642de2..0000000000
--- a/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130306191917)
-class AddActiveFieldToStockLocations < ActiveRecord::Migration
- def change
- add_column :spree_stock_locations, :active, :boolean, :default => true
- end
-end
diff --git a/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb b/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb
deleted file mode 100644
index 839e3b3d09..0000000000
--- a/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130306195650)
-class AddBackorderableToStockItem < ActiveRecord::Migration
- def change
- add_column :spree_stock_items, :backorderable, :boolean, :default => true
- end
-end
diff --git a/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb b/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb
deleted file mode 100644
index c991b94e4a..0000000000
--- a/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130307161754)
-class AddDefaultQuantityToStockMovement < ActiveRecord::Migration
- def change
- change_column :spree_stock_movements, :quantity, :integer, :default => 0
- end
-end
diff --git a/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb b/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb
deleted file mode 100644
index 7e0f0987b7..0000000000
--- a/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# This migration comes from spree (originally 20130318151756)
-class AddSourceAndDestinationToStockMovements < ActiveRecord::Migration
- def change
- change_table :spree_stock_movements do |t|
- t.references :source, polymorphic: true
- t.references :destination, polymorphic: true
- end
- end
-end
diff --git a/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb b/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb
deleted file mode 100644
index 7c1a74679a..0000000000
--- a/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# This migration comes from spree (originally 20130319183250)
-class AddOriginatorToStockMovement < ActiveRecord::Migration
- def change
- change_table :spree_stock_movements do |t|
- t.references :originator, polymorphic: true
- end
- end
-end
diff --git a/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb b/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb
deleted file mode 100644
index 6735614f4e..0000000000
--- a/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# This migration comes from spree (originally 20130319190507)
-class DropSourceAndDestinationFromStockMovement < ActiveRecord::Migration
- def up
- change_table :spree_stock_movements do |t|
- t.remove_references :source, :polymorphic => true
- t.remove_references :destination, :polymorphic => true
- end
- end
-
- def down
- change_table :spree_stock_movements do |t|
- t.references :source, polymorphic: true
- t.references :destination, polymorphic: true
- end
- end
-end
diff --git a/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb b/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb
deleted file mode 100644
index 4f759427ee..0000000000
--- a/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# This migration comes from spree (originally 20130325163316)
-class MigrateInventoryUnitSoldToOnHand < ActiveRecord::Migration
- def up
- Spree::InventoryUnit.where(:state => 'sold').update_all(:state => 'on_hand')
- end
-
- def down
- Spree::InventoryUnit.where(:state => 'on_hand').update_all(:state => 'sold')
- end
-end
diff --git a/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb b/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb
deleted file mode 100644
index 54d85f76a4..0000000000
--- a/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130326175857)
-class AddStockLocationToRma < ActiveRecord::Migration
- def change
- add_column :spree_return_authorizations, :stock_location_id, :integer
- end
-end
diff --git a/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb b/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb
deleted file mode 100644
index f5c1b5a0cf..0000000000
--- a/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# This migration comes from spree (originally 20130328130308)
-class UpdateShipmentStateForCanceledOrders < ActiveRecord::Migration
- def up
- shipments = Spree::Shipment.joins(:order).
- where("spree_orders.state = 'canceled'")
- case Spree::Shipment.connection.adapter_name
- when "SQLite3"
- shipments.update_all("state = 'cancelled'")
- when "MySQL" || "PostgreSQL"
- shipments.update_all("spree_shipments.state = 'cancelled'")
- end
- end
-
- def down
- end
-end
diff --git a/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb b/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb
deleted file mode 100644
index c522a765cc..0000000000
--- a/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# This migration comes from spree (originally 20130329134939)
-class RemoveStockItemAndVariantLock < ActiveRecord::Migration
- def up
- # we are moving to pessimistic locking on stock_items
- remove_column :spree_stock_items, :lock_version
-
- # variants no longer manage their count_on_hand so we are removing their lock
- remove_column :spree_variants, :lock_version
- end
-
- def down
- add_column :spree_stock_items, :lock_version, :integer
- add_column :spree_variants, :lock_version, :integer
- end
-end
diff --git a/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb b/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb
deleted file mode 100644
index 67c24f568d..0000000000
--- a/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# This migration comes from spree (originally 20130417123427)
-class AddShippingRatesToShipments < ActiveRecord::Migration
- def up
- Spree::Shipment.all.each do |shipment|
- shipment.shipping_rates.create!(:shipping_method_id => shipment.shipping_method_id,
- :cost => shipment.cost,
- :selected => true)
- end
-
- remove_column :spree_shipments, :shipping_method_id
- end
-
- def down
- add_column :spree_shipments, :shipping_method_id, :integer
- end
-end
diff --git a/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb b/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb
deleted file mode 100644
index 1b73d9b176..0000000000
--- a/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# This migration comes from spree (originally 20130418125341)
-class CreateSpreeStockTransfers < ActiveRecord::Migration
- def change
- create_table :spree_stock_transfers do |t|
- t.string :type
- t.string :reference_number
- t.integer :source_location_id
- t.integer :destination_location_id
- t.timestamps
- end
-
- add_index :spree_stock_transfers, :source_location_id
- add_index :spree_stock_transfers, :destination_location_id
- end
-end
diff --git a/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb b/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb
deleted file mode 100644
index 29cb947a56..0000000000
--- a/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130423110707)
-class DropProductsCountOnHand < ActiveRecord::Migration
- def up
- remove_column :spree_products, :count_on_hand
- end
-end
diff --git a/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb b/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb
deleted file mode 100644
index 64b9ccb108..0000000000
--- a/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130423223847)
-class SetDefaultShippingRateCost < ActiveRecord::Migration
- def change
- change_column :spree_shipping_rates, :cost, :decimal, default: 0, precision: 8, scale: 2
- end
-end
diff --git a/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb b/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb
deleted file mode 100644
index cf06743da0..0000000000
--- a/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# This migration comes from spree (originally 20130509115210)
-class AddNumberToStockTransfer < ActiveRecord::Migration
- def up
- remove_index :spree_stock_transfers, :source_location_id
- remove_index :spree_stock_transfers, :destination_location_id
-
- rename_column :spree_stock_transfers, :reference_number, :reference
- add_column :spree_stock_transfers, :number, :string
-
- Spree::StockTransfer.all.each do |transfer|
- transfer.send(:generate_stock_transfer_number)
- transfer.save!
- end
-
- add_index :spree_stock_transfers, :number
- add_index :spree_stock_transfers, :source_location_id
- add_index :spree_stock_transfers, :destination_location_id
- end
-
- def down
- rename_column :spree_stock_transfers, :reference, :reference_number
- remove_column :spree_stock_transfers, :number, :string
- end
-end
diff --git a/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb b/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb
deleted file mode 100644
index cd089f846d..0000000000
--- a/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130514151929)
-class AddSkuIndexToSpreeVariants < ActiveRecord::Migration
- def change
- add_index :spree_variants, :sku
- end
-end
diff --git a/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb b/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb
deleted file mode 100644
index 29939c59e6..0000000000
--- a/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130515180736)
-class AddBackorderableDefaultToSpreeStockLocation < ActiveRecord::Migration
- def change
- add_column :spree_stock_locations, :backorderable_default, :boolean, default: true
- end
-end
diff --git a/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb b/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb
deleted file mode 100644
index bfc55eac56..0000000000
--- a/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130516151222)
-class AddPropageAllVariantsToSpreeStockLocation < ActiveRecord::Migration
- def change
- add_column :spree_stock_locations, :propagate_all_variants, :boolean, default: true
- end
-end
diff --git a/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb b/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb
deleted file mode 100644
index 5c7ee6dd95..0000000000
--- a/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130611054351)
-class RenameShippingMethodsZonesToSpreeShippingMethodsZones < ActiveRecord::Migration
- def change
- rename_table :shipping_methods_zones, :spree_shipping_methods_zones
- end
-end
diff --git a/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb b/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb
deleted file mode 100644
index c804d9a1f7..0000000000
--- a/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130708052307)
-class AddDeletedAtToSpreeTaxRates < ActiveRecord::Migration
- def change
- add_column :spree_tax_rates, :deleted_at, :datetime
- end
-end
diff --git a/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb b/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb
deleted file mode 100644
index 42c60bd3f3..0000000000
--- a/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# This migration comes from spree (originally 20130711200933)
-class RemoveLockVersionFromInventoryUnits < ActiveRecord::Migration
- def change
- # we are moving to pessimistic locking on stock_items
- remove_column :spree_inventory_units, :lock_version
- end
-end
diff --git a/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb b/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb
deleted file mode 100644
index d54222f559..0000000000
--- a/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130718042445)
-class AddCostPriceToLineItem < ActiveRecord::Migration
- def change
- add_column :spree_line_items, :cost_price, :decimal, :precision => 8, :scale => 2
- end
-end
diff --git a/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb b/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb
deleted file mode 100644
index a05f4279a4..0000000000
--- a/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# This migration comes from spree (originally 20130718233855)
-class SetBackorderableToDefaultToFalse < ActiveRecord::Migration
- def change
- change_column :spree_stock_items, :backorderable, :boolean, :default => false
- change_column :spree_stock_locations, :backorderable_default, :boolean, :default => false
- end
-end
diff --git a/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb b/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb
deleted file mode 100644
index fe59c0fc21..0000000000
--- a/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130725031716)
-class AddCreatedByIdToSpreeOrders < ActiveRecord::Migration
- def change
- add_column :spree_orders, :created_by_id, :integer
- end
-end
diff --git a/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb b/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb
deleted file mode 100644
index c4c279ca4c..0000000000
--- a/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130729214043)
-class IndexCompletedAtOnSpreeOrders < ActiveRecord::Migration
- def change
- add_index :spree_orders, :completed_at
- end
-end
diff --git a/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb b/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb
deleted file mode 100644
index 2b7e1a51bc..0000000000
--- a/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# This migration comes from spree (originally 20130802014537)
-class AddTaxCategoryIdToSpreeLineItems < ActiveRecord::Migration
- def change
- add_column :spree_line_items, :tax_category_id, :integer
- end
-end
diff --git a/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb b/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb
deleted file mode 100644
index 4ce74249b3..0000000000
--- a/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# This migration comes from spree (originally 20130802022321)
-class MigrateTaxCategoriesToLineItems < ActiveRecord::Migration
- def change
- Spree::LineItem.includes(:variant => { :product => :tax_category }).find_in_batches do |line_items|
- line_items.each do |line_item|
- next if line_item.variant.nil?
- next if line_item.variant.product.nil?
- next if line_item.product.nil?
- next unless line_item.product.tax_category.present?
- line_item.update_column(:tax_category_id, line_item.product.tax_category.id)
- end
- end
- end
-end
diff --git a/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb b/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb
deleted file mode 100644
index 0821fbef61..0000000000
--- a/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class RemoveCreditCardFromSubscriptions < ActiveRecord::Migration
- def up
- remove_foreign_key :subscriptions, name: :subscriptions_credit_card_id_fk
- remove_index :subscriptions, :credit_card_id
- remove_column :subscriptions, :credit_card_id
- end
-
- def down
- add_column :subscriptions, :credit_card_id, :integer
- add_index :subscriptions, :credit_card_id
- add_foreign_key :subscriptions, :spree_credit_cards, name: :subscriptions_credit_card_id_fk, column: :credit_card_id
- end
-end
diff --git a/db/migrate/20180812214434_drop_carts.rb b/db/migrate/20180812214434_drop_carts.rb
deleted file mode 100644
index f3dfb36ee7..0000000000
--- a/db/migrate/20180812214434_drop_carts.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class DropCarts < ActiveRecord::Migration
- def change
- remove_foreign_key :spree_orders, column: :cart_id
- remove_column :spree_orders, :cart_id
- drop_table :carts
- end
-end
diff --git a/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb b/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb
deleted file mode 100644
index 93b2853208..0000000000
--- a/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Since OFN has only a single default StockLocation, variants in OFN can only
-# have a stock item. By adding this unique index we constraint that at DB level
-# ensuring data integrity.
-class AddUniquenessOfVariantIdToSpreeStockItems < ActiveRecord::Migration
- def change
- add_index :spree_stock_items, :variant_id, unique: true
- end
-end
diff --git a/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb b/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb
deleted file mode 100644
index 0ee5849afd..0000000000
--- a/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# This migration is an OFN specific migration that enforces an order to have a single shipment at all times
-class AddUniquenessOfOrderIdToSpreeShipments < ActiveRecord::Migration
- def change
- Spree::InventoryUnit.connection.schema_cache.clear!
- Spree::InventoryUnit.reset_column_information
-
- destroy_all_but_latest_shipments
-
- remove_index :spree_shipments, :order_id
- add_index :spree_shipments, :order_id, unique: true
- end
-
- private
-
- # Destroy all but the latest shipment in each order
- def destroy_all_but_latest_shipments
- latest_shipments = Spree::Shipment.
- select("order_id, MAX(updated_at) updated_at").
- group(:order_id).
- having("count(*) > 1")
-
- all_duplicated_shipments = Spree::Shipment.
- joins("INNER JOIN (#{latest_shipments.to_sql}) latest_shipments ON spree_shipments.order_id = latest_shipments.order_id")
- backup_to_csv(all_duplicated_shipments)
-
- shipments_to_delete = Spree::Shipment.
- joins("INNER JOIN (#{latest_shipments.to_sql}) latest_shipments ON spree_shipments.order_id = latest_shipments.order_id AND spree_shipments.updated_at != latest_shipments.updated_at")
- remove_association_to_adjustments(shipments_to_delete)
- shipments_to_delete.destroy_all
- end
-
- def remove_association_to_adjustments(shipments)
- Spree::Adjustment.
- joins("INNER JOIN (#{shipments.to_sql}) shipments_to_delete ON shipments_to_delete.id = spree_adjustments.source_id and spree_adjustments.source_type = 'Spree::Shipment'").
- update_all(source_id: nil, source_type: nil, originator_id: nil, originator_type: nil, mandatory: nil)
- end
-
- def backup_to_csv(shipments)
- CSV.open(csv_path, "w") do |csv|
- csv << csv_header_row
-
- shipments.each do |shipment|
- csv << shipment_csv_row(shipment)
- end
- end
- end
-
- def csv_header_row
- %w(
- id
- tracking
- number
- order_number
- shipping_method_name
- cost
- state
- shipped_at
- created_at
- updated_at
- address_json
- )
- end
-
- def shipment_csv_row(shipment)
- [
- shipment.id,
- shipment.tracking,
- shipment.number,
- shipment.order.number,
- shipment.shipping_method.andand.name,
- shipment.cost,
- shipment.state,
- shipment.shipped_at,
- shipment.created_at,
- shipment.updated_at,
- shipment.address.to_json
- ]
- end
-
- def csv_path
- ensure_reports_path_exists
- reports_path.join("duplicated_shipments_backup.csv")
- end
-
- def reports_path
- Rails.root.join("reports")
- end
-
- def ensure_reports_path_exists
- Dir.mkdir(reports_path) unless File.exist?(reports_path)
- end
-end
diff --git a/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb b/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb
deleted file mode 100644
index eaae250a18..0000000000
--- a/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class RemoveShippingMethodNameFromSpreeLineItems < ActiveRecord::Migration
- def up
- remove_column :spree_line_items, :shipping_method_name
- end
-
- def down
- add_column :spree_line_items, :shipping_method_name, :string
- end
-end
diff --git a/db/migrate/20181008201815_update_instagram_data.rb b/db/migrate/20181008201815_update_instagram_data.rb
deleted file mode 100644
index d1a45dc155..0000000000
--- a/db/migrate/20181008201815_update_instagram_data.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class UpdateInstagramData < ActiveRecord::Migration
- def change
- Enterprise.where("instagram like ?", "%instagram.com%").find_each do |e|
- e.instagram = e.instagram.split('/').last
- e.save
- end
- end
-end
diff --git a/db/migrate/20181010093850_fix_variants_missing_unit_value.rb b/db/migrate/20181010093850_fix_variants_missing_unit_value.rb
deleted file mode 100644
index c4226d0dc2..0000000000
--- a/db/migrate/20181010093850_fix_variants_missing_unit_value.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# Fixes variants whose product.variant_unit is 'weight' and miss a unit_value,
-# showing 1 unit of the specified weight. That is, if the user chose Kg, it'll
-# display 1 as unit.
-class FixVariantsMissingUnitValue < ActiveRecord::Migration
- HUMAN_UNIT_VALUE = 1
-
- def up
- logger.info "Fixing variants missing unit_value...\n"
-
- variants_missing_unit_value.find_each do |variant|
- logger.info "Processing variant #{variant.id}..."
-
- fix_unit_value(variant)
- end
-
- logger.info "Done!"
- end
-
- def down
- end
-
- private
-
- def variants_missing_unit_value
- Spree::Variant
- .joins(:product)
- .readonly(false)
- .where(
- spree_products: { variant_unit: 'weight' },
- spree_variants: { unit_value: nil }
- )
- end
-
- def fix_unit_value(variant)
- variant.unit_value = HUMAN_UNIT_VALUE * variant.product.variant_unit_scale
-
- if variant.save
- logger.info "Successfully fixed variant #{variant.id}"
- else
- logger.info "Failed fixing variant #{variant.id}"
- end
-
- logger.info ""
- end
-
- def logger
- @logger ||= Logger.new('log/migrate.log')
- end
-end
diff --git a/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb b/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb
deleted file mode 100644
index d8140c9bf3..0000000000
--- a/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-class RevokeVariantOverrideswithoutPermissions < ActiveRecord::Migration
- def up
- # This process was executed when the permission_revoked_at colum was created (see AddPermissionRevokedAtToVariantOverrides)
- # It needs to be repeated due to #2739
- variant_override_hubs = Enterprise.where(id: VariantOverride.select(:hub_id).uniq)
-
- variant_override_hubs.find_each do |hub|
- permitting_producer_ids = hub.relationships_as_child
- .with_permission(:create_variant_overrides).pluck(:parent_id)
-
- variant_overrides_with_revoked_permissions = VariantOverride.for_hubs(hub)
- .joins(variant: :product).where("spree_products.supplier_id NOT IN (?)", permitting_producer_ids)
-
- variant_overrides_with_revoked_permissions.update_all(permission_revoked_at: Time.now)
- end
- end
-end
diff --git a/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb b/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb
deleted file mode 100644
index a04bd5dfff..0000000000
--- a/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AllowAllSuppliersOwnVariantOverrides < ActiveRecord::Migration
- def up
- # This migration is fixing a detail of previous migration RevokeVariantOverrideswithoutPermissions
- # Here we allow all variant_overrides where hub_id is the products supplier_id
- # This is needed when the supplier herself uses the inventory to manage stock and not the catalog
- owned_variant_overrides = VariantOverride.unscoped
- .joins(variant: :product).where("spree_products.supplier_id = variant_overrides.hub_id")
-
- owned_variant_overrides.update_all(permission_revoked_at: nil)
- end
-end
-
diff --git a/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb b/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb
deleted file mode 100644
index f8e15b3414..0000000000
--- a/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class UpdateWeightCalculatorTypeClassName < ActiveRecord::Migration
- def up
- Spree::Calculator.connection.execute("UPDATE spree_calculators SET type = 'Calculator::Weight' WHERE type = 'OpenFoodNetwork::Calculator::Weight'")
- end
-
- def down
- Spree::Calculator.connection.execute("UPDATE spree_calculators SET type = 'OpenFoodNetwork::Calculator::Weight' WHERE type = 'Calculator::Weight'")
- end
-end
diff --git a/db/migrate/20181123012635_associate_customers_to_users.rb b/db/migrate/20181123012635_associate_customers_to_users.rb
deleted file mode 100644
index 95fab93677..0000000000
--- a/db/migrate/20181123012635_associate_customers_to_users.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# When we introduced the Customer model, we didn't associate any existing
-# customers with users that have the same email address.
-# Later we decided to create that association when users sign up. But we didn't
-# update all the existing customers. We do that now for data consistency and to
-# solve several bugs.
-#
-# - https://github.com/openfoodfoundation/openfoodnetwork/pull/2084
-# - https://github.com/openfoodfoundation/openfoodnetwork/issues/2841
-class AssociateCustomersToUsers < ActiveRecord::Migration
- class Customer < ActiveRecord::Base
- end
-
- def up
- save_customers
- execute "UPDATE customers
- SET user_id = spree_users.id
- FROM spree_users
- WHERE customers.email = spree_users.email
- AND customers.user_id IS NULL;"
- end
-
- def down
- customers = backed_up_customers
- Customer.where(id: customers).update_all(user_id: nil)
- end
-
- def save_customers
- customers = Customer.
- joins("INNER JOIN spree_users ON customers.email = spree_users.email").
- where(user_id: nil).all
-
- File.write(backup_file, YAML.dump(customers))
- end
-
- def backed_up_customers
- YAML.load(File.read(backup_file))
- end
-
- def backup_file
- File.join("log", "customers_without_user_association.log")
- end
-end
diff --git a/db/migrate/20181128054803_old_migrations_removed.rb b/db/migrate/20181128054803_old_migrations_removed.rb
new file mode 100644
index 0000000000..47d233f0aa
--- /dev/null
+++ b/db/migrate/20181128054803_old_migrations_removed.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class OldMigrationsRemoved < ActiveRecord::Migration
+ def up
+ raise StandardError, <<-MESSAGE
+
+ You haven't updated your dev environment in a long time!
+ Legacy migration files before 2019 have now been removed.
+ Run `rake db:schema:load` before running `rake db:migrate`.
+
+ MESSAGE
+ end
+end
diff --git a/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb b/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb
deleted file mode 100644
index 6627dca015..0000000000
--- a/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb
+++ /dev/null
@@ -1,165 +0,0 @@
-# This simplifies variant overrides to have only the following combinations:
-#
-# on_demand | count_on_hand
-# -----------+---------------
-# true | nil
-# false | set
-# nil | nil
-#
-# Refer to the table {here}[https://github.com/openfoodfoundation/openfoodnetwork/issues/3067] for
-# the effect of different variant and variant override stock configurations.
-#
-# Furthermore, this will allow all existing variant overrides to satisfy the newly added model
-# validation rules.
-class SimplifyVariantOverrideStockSettings < ActiveRecord::Migration
- class VariantOverride < ActiveRecord::Base
- belongs_to :variant
- belongs_to :hub, class_name: "Enterprise"
-
- scope :with_count_on_hand, -> { where("count_on_hand IS NOT NULL") }
- scope :without_count_on_hand, -> { where(count_on_hand: nil) }
- end
-
- class Variant < ActiveRecord::Base
- self.table_name = "spree_variants"
-
- belongs_to :product
-
- def name
- namer = OpenFoodNetwork::OptionValueNamer.new(self)
- namer.name
- end
- end
-
- class Product < ActiveRecord::Base
- self.table_name = "spree_products"
-
- belongs_to :supplier, class_name: "Enterprise"
- end
-
- class Enterprise < ActiveRecord::Base; end
-
- def up
- ensure_reports_path_exists
-
- CSV.open(csv_path, "w") do |csv|
- csv << csv_header_row
-
- update_use_producer_stock_settings_with_count_on_hand(csv)
- update_on_demand_with_count_on_hand(csv)
- update_limited_stock_without_count_on_hand(csv)
- end
-
- split_csv_by_distributor
- end
-
- def down
- CSV.foreach(csv_path, headers: true) do |row|
- VariantOverride.where(id: row["variant_override_id"])
- .update_all(on_demand: row["previous_on_demand"],
- count_on_hand: row["previous_count_on_hand"])
- end
- end
-
- private
-
- def reports_path
- Rails.root.join("reports", "SimplifyVariantOverrideStockSettings")
- end
-
- def ensure_reports_path_exists
- Dir.mkdir(reports_path) unless File.exist?(reports_path)
- end
-
- def csv_path
- reports_path.join("changed_variant_overrides.csv")
- end
-
- def distributor_csv_path(name, id)
- reports_path.join("changed_variant_overrides-#{name.parameterize('_')}-#{id}.csv")
- end
-
- # When on_demand is nil but count_on_hand is set, force limited stock.
- def update_use_producer_stock_settings_with_count_on_hand(csv)
- variant_overrides = VariantOverride.where(on_demand: nil).with_count_on_hand
- update_variant_overrides_and_log(csv, variant_overrides) do |variant_override|
- variant_override.update_attributes!(on_demand: false)
- end
- end
-
- # Clear count_on_hand if forcing on demand.
- def update_on_demand_with_count_on_hand(csv)
- variant_overrides = VariantOverride.where(on_demand: true).with_count_on_hand
- update_variant_overrides_and_log(csv, variant_overrides) do |variant_override|
- variant_override.update_attributes!(count_on_hand: nil)
- end
- end
-
- # When on_demand is false but count on hand is not specified, set this to use producer stock
- # settings.
- def update_limited_stock_without_count_on_hand(csv)
- variant_overrides = VariantOverride.where(on_demand: false).without_count_on_hand
- update_variant_overrides_and_log(csv, variant_overrides) do |variant_override|
- variant_override.update_attributes!(on_demand: nil)
- end
- end
-
- def update_variant_overrides_and_log(csv, variant_overrides)
- variant_overrides.find_each do |variant_override|
- csv << variant_override_log_row(variant_override) do
- yield variant_override
- end
- end
- end
-
- def csv_header_row
- %w(
- variant_override_id
- distributor_name distributor_id
- producer_name producer_id
- product_name product_id
- variant_description variant_id
- previous_on_demand previous_count_on_hand
- updated_on_demand updated_count_on_hand
- )
- end
-
- def variant_override_log_row(variant_override)
- variant = variant_override.variant
- distributor = variant_override.hub
- product = variant.andand.product
- supplier = product.andand.supplier
-
- row = [
- variant_override.id,
- distributor.andand.name, distributor.andand.id,
- supplier.andand.name, supplier.andand.id,
- product.andand.name, product.andand.id,
- variant.andand.name, variant.andand.id,
- variant_override.on_demand, variant_override.count_on_hand
- ]
-
- yield variant_override
-
- row + [variant_override.on_demand, variant_override.count_on_hand]
- end
-
- def split_csv_by_distributor
- table = CSV.read(csv_path)
- distributor_ids = table[1..-1].map { |row| row[2] }.uniq # Don't use the header row.
-
- distributor_ids.each do |distributor_id|
- distributor_data_rows = filter_data_rows_for_distributor(table[1..-1], distributor_id)
- distributor_name = distributor_data_rows.first[1]
-
- CSV.open(distributor_csv_path(distributor_name, distributor_id), "w") do |csv|
- csv << table[0] # Header row
- distributor_data_rows.each { |row| csv << row }
- end
- end
- end
-
- def filter_data_rows_for_distributor(data_rows, distributor_id)
- data_rows.select { |row| row[2] == distributor_id }
- end
-end
diff --git a/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb b/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb
new file mode 100644
index 0000000000..cb8ef67b0e
--- /dev/null
+++ b/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb
@@ -0,0 +1,5 @@
+class AddUserIdIndexToSpreeOrders < ActiveRecord::Migration
+ def change
+ add_index :spree_orders, :user_id
+ end
+end
diff --git a/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb b/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb
new file mode 100644
index 0000000000..eadc5a7c50
--- /dev/null
+++ b/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb
@@ -0,0 +1,5 @@
+class AddSupplierIdIndexToSpreeProducts < ActiveRecord::Migration
+ def change
+ add_index :spree_products, :supplier_id
+ end
+end
diff --git a/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb b/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb
new file mode 100644
index 0000000000..5cac7dab5b
--- /dev/null
+++ b/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb
@@ -0,0 +1,9 @@
+class IncreaseCharactersOfLocaleInSpreeUsers < ActiveRecord::Migration
+ def up
+ change_column :spree_users, :locale, :string, limit: 6
+ end
+
+ def down
+ change_column :spree_users, :locale, :string, limit: 5
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 36cd344ea1..d786441da1 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20200327105910) do
+ActiveRecord::Schema.define(:version => 20200406085833) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -578,7 +578,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do
add_index "spree_orders", ["number"], name: "index_orders_on_number", using: :btree
add_index "spree_orders", ["distributor_id"], name: "index_spree_orders_on_distributor_id", using: :btree
add_index "spree_orders", ["order_cycle_id"], name: "index_spree_orders_on_order_cycle_id", using: :btree
-
+ add_index "spree_orders", ["user_id"], name: "index_spree_orders_on_user_id", using: :btree
create_table "spree_payment_methods", force: true do |t|
t.string "type"
@@ -728,6 +728,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do
add_index "spree_products", ["permalink"], name: "index_products_on_permalink", using: :btree
add_index "spree_products", ["permalink"], name: "permalink_idx_unique", unique: true, using: :btree
add_index "spree_products", ["primary_taxon_id"], name: "index_spree_products_on_primary_taxon_id", using: :btree
+ add_index "spree_products", ["supplier_id"], name: "index_spree_products_on_supplier_id"
create_table "spree_products_promotion_rules", id: false, force: true do |t|
t.integer "product_id"
@@ -1050,7 +1051,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do
t.datetime "reset_password_sent_at"
t.string "api_key", limit: 40
t.integer "enterprise_limit", default: 5, null: false
- t.string "locale", limit: 5
+ t.string "locale", limit: 6
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
diff --git a/docker-compose.yml b/docker-compose.yml
index 5025cfd929..f4407eb6a4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -28,10 +28,7 @@ services:
ADMIN_PASSWORD: ofn123
OFN_DB_HOST: db
command: >
- bash -c "(bundle check || bundle install) &&
- wait-for-it -t 30 db:5432 &&
- bundle exec rake db:reset &&
- bundle exec rake db:test:prepare ofn:sample_data || true &&
+ bash -c "wait-for-it -t 30 db:5432 &&
rm -f tmp/pids/server.pid &&
bundle exec rails s -p 3000 -b '0.0.0.0'"
diff --git a/engines/catalog/config/routes.rb b/engines/catalog/config/routes.rb
index a56f4a0b70..166898de46 100644
--- a/engines/catalog/config/routes.rb
+++ b/engines/catalog/config/routes.rb
@@ -1,2 +1,2 @@
-Catalog::Engine.routes.draw do
+Openfoodnetwork::Application.routes.prepend do
end
diff --git a/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb b/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb
new file mode 100644
index 0000000000..08b6c602c5
--- /dev/null
+++ b/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb
@@ -0,0 +1,64 @@
+module OrderManagement
+ module Reports
+ class EnterpriseFeeSummariesController < Spree::Admin::BaseController
+ before_filter :load_report_parameters
+ before_filter :load_permissions
+
+ def new; end
+
+ def create
+ return respond_to_invalid_parameters unless @report_parameters.valid?
+
+ @report_parameters.authorize!(@permissions)
+
+ @report = report_klass::ReportService.new(@permissions, @report_parameters)
+ renderer.render(self)
+ rescue ::Reports::Authorizer::ParameterNotAllowedError => e
+ flash[:error] = e.message
+ render_report_form
+ end
+
+ private
+
+ def respond_to_invalid_parameters
+ flash[:error] = I18n.t("invalid_filter_parameters", scope: i18n_scope)
+ render_report_form
+ end
+
+ def i18n_scope
+ "order_management.reports.enterprise_fee_summary"
+ end
+
+ def render_report_form
+ render action: :new
+ end
+
+ def report_klass
+ OrderManagement::Reports::EnterpriseFeeSummary
+ end
+
+ def load_report_parameters
+ @report_parameters = report_klass::Parameters.new(params[:report] || {})
+ end
+
+ def load_permissions
+ @permissions = report_klass::Permissions.new(spree_current_user)
+ end
+
+ def report_renderer_klass
+ case params[:report_format]
+ when "csv"
+ report_klass::Renderers::CsvRenderer
+ when nil, "", "html"
+ report_klass::Renderers::HtmlRenderer
+ else
+ raise Reports::UnsupportedReportFormatException
+ end
+ end
+
+ def renderer
+ @renderer ||= report_renderer_klass.new(@report)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/count.rb b/engines/order_management/app/services/order_management/subscriptions/count.rb
new file mode 100644
index 0000000000..80f066d209
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/count.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ class Count
+ def initialize(order_cycles)
+ @order_cycles = order_cycles
+ end
+
+ def for(order_cycle_id)
+ active[order_cycle_id] || 0
+ end
+
+ private
+
+ attr_accessor :order_cycles
+
+ def active
+ return @active unless @active.nil?
+ return @active = [] if order_cycles.blank?
+
+ @active ||= ProxyOrder.
+ not_canceled.
+ group(:order_cycle_id).
+ where(order_cycle_id: order_cycles).
+ count
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/estimator.rb b/engines/order_management/app/services/order_management/subscriptions/estimator.rb
new file mode 100644
index 0000000000..e358e031bf
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/estimator.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'open_food_network/scope_variant_to_hub'
+
+# Responsible for estimating prices and fees for subscriptions
+# Used by Form as part of the create/update process
+# The values calculated here are intended to be persisted in the db
+
+module OrderManagement
+ module Subscriptions
+ class Estimator
+ def initialize(subscription)
+ @subscription = subscription
+ end
+
+ def estimate!
+ assign_price_estimates
+ assign_fee_estimates
+ end
+
+ private
+
+ attr_accessor :subscription
+
+ delegate :subscription_line_items, :shipping_method, :payment_method, :shop, to: :subscription
+
+ def assign_price_estimates
+ subscription_line_items.each do |item|
+ item.price_estimate =
+ price_estimate_for(item.variant, item.price_estimate_was)
+ end
+ end
+
+ def price_estimate_for(variant, fallback)
+ return fallback unless fee_calculator && variant
+
+ scoper.scope(variant)
+ fees = fee_calculator.indexed_fees_for(variant)
+ (variant.price + fees).to_d
+ end
+
+ def fee_calculator
+ return @fee_calculator unless @fee_calculator.nil?
+
+ next_oc = subscription.schedule.andand.current_or_next_order_cycle
+ return nil unless shop && next_oc
+
+ @fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, next_oc)
+ end
+
+ def scoper
+ OpenFoodNetwork::ScopeVariantToHub.new(shop)
+ end
+
+ def assign_fee_estimates
+ subscription.shipping_fee_estimate = shipping_fee_estimate
+ subscription.payment_fee_estimate = payment_fee_estimate
+ end
+
+ def shipping_fee_estimate
+ shipping_method.calculator.compute(subscription)
+ end
+
+ def payment_fee_estimate
+ payment_method.calculator.compute(subscription)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/form.rb b/engines/order_management/app/services/order_management/subscriptions/form.rb
new file mode 100644
index 0000000000..2e354835be
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/form.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'order_management/subscriptions/proxy_order_syncer'
+
+module OrderManagement
+ module Subscriptions
+ class Form
+ attr_accessor :subscription, :subscription_params, :order_update_issues,
+ :validator, :order_syncer, :estimator
+
+ delegate :json_errors, :valid?, to: :validator
+ delegate :order_update_issues, to: :order_syncer
+
+ def initialize(subscription, subscription_params = {})
+ @subscription = subscription
+ @subscription_params = subscription_params
+ @estimator = OrderManagement::Subscriptions::Estimator.new(subscription)
+ @validator = OrderManagement::Subscriptions::Validator.new(subscription)
+ @order_syncer = OrderSyncer.new(subscription)
+ end
+
+ def save
+ subscription.assign_attributes(subscription_params)
+ return false unless valid?
+
+ subscription.transaction do
+ estimator.estimate!
+ proxy_order_syncer.sync!
+ order_syncer.sync!
+ subscription.save!
+ end
+ end
+
+ private
+
+ def proxy_order_syncer
+ OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscription)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb b/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb
new file mode 100644
index 0000000000..6d90236466
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ class PaymentSetup
+ def initialize(order)
+ @order = order
+ end
+
+ def call!
+ payment = create_payment
+ return if @order.errors.any?
+
+ payment.update_attributes(amount: @order.outstanding_balance)
+ payment
+ end
+
+ private
+
+ def create_payment
+ payment = OrderPaymentFinder.new(@order).last_pending_payment
+ return payment if payment.present?
+
+ @order.payments.create(
+ payment_method_id: @order.subscription.payment_method_id
+ )
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb b/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb
new file mode 100644
index 0000000000..4f45e7421f
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: false
+
+module OrderManagement
+ module Subscriptions
+ class ProxyOrderSyncer
+ attr_reader :subscription
+
+ delegate :order_cycles, :proxy_orders, :begins_at, :ends_at, to: :subscription
+
+ def initialize(subscriptions)
+ case subscriptions
+ when Subscription
+ @subscription = subscriptions
+ when ActiveRecord::Relation
+ @subscriptions = subscriptions.not_ended.not_canceled
+ else
+ raise "ProxyOrderSyncer must be initialized with " \
+ "an instance of Subscription or ActiveRecord::Relation"
+ end
+ end
+
+ def sync!
+ return sync_subscriptions! if @subscriptions
+
+ return initialise_proxy_orders! unless @subscription.id
+
+ sync_subscription!
+ end
+
+ private
+
+ def sync_subscriptions!
+ @subscriptions.each do |subscription|
+ @subscription = subscription
+ sync_subscription!
+ end
+ end
+
+ def initialise_proxy_orders!
+ uninitialised_order_cycle_ids.each do |order_cycle_id|
+ Rails.logger.info "Initializing Proxy Order " \
+ "of subscription #{@subscription.id} in order cycle #{order_cycle_id}"
+ proxy_orders << ProxyOrder.new(subscription: subscription, order_cycle_id: order_cycle_id)
+ end
+ end
+
+ def sync_subscription!
+ Rails.logger.info "Syncing Proxy Orders of subscription #{@subscription.id}"
+ create_proxy_orders!
+ remove_orphaned_proxy_orders!
+ end
+
+ def create_proxy_orders!
+ return unless not_closed_in_range_order_cycles.any?
+
+ query = "INSERT INTO proxy_orders (subscription_id, order_cycle_id, updated_at, created_at)"
+ query << " VALUES #{insert_values}"
+ query << " ON CONFLICT DO NOTHING"
+
+ ActiveRecord::Base.connection.exec_query(query)
+ end
+
+ def uninitialised_order_cycle_ids
+ not_closed_in_range_order_cycles.pluck(:id) - proxy_orders.map(&:order_cycle_id)
+ end
+
+ def remove_orphaned_proxy_orders!
+ orphaned_proxy_orders.where(nil).delete_all
+ end
+
+ # Remove Proxy Orders that have not been placed yet
+ # and are in Order Cycles that are out of range
+ def orphaned_proxy_orders
+ orphaned = proxy_orders.where(placed_at: nil)
+ order_cycle_ids = in_range_order_cycles.pluck(:id)
+ return orphaned unless order_cycle_ids.any?
+
+ orphaned.where('order_cycle_id NOT IN (?)', order_cycle_ids)
+ end
+
+ def insert_values
+ now = Time.now.utc.iso8601
+ not_closed_in_range_order_cycles
+ .map{ |oc| "(#{subscription.id},#{oc.id},'#{now}','#{now}')" }
+ .join(",")
+ end
+
+ def not_closed_in_range_order_cycles
+ in_range_order_cycles.merge(OrderCycle.not_closed)
+ end
+
+ def in_range_order_cycles
+ order_cycles.where("orders_close_at >= ? AND orders_close_at <= ?",
+ begins_at,
+ ends_at || 100.years.from_now)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb b/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb
new file mode 100644
index 0000000000..37e3a097f3
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ class StripePaymentSetup
+ def initialize(order)
+ @order = order
+ @payment = OrderPaymentFinder.new(@order).last_pending_payment
+ end
+
+ def call!
+ return if @payment.blank?
+
+ ensure_payment_source
+ @payment
+ end
+
+ private
+
+ def ensure_payment_source
+ return unless stripe_payment_method? && !card_set?
+
+ if saved_credit_card.present? && allow_charges?
+ use_saved_credit_card
+ else
+ @order.errors.add(:base, :no_card)
+ end
+ end
+
+ def stripe_payment_method?
+ [Spree::Gateway::StripeConnect,
+ Spree::Gateway::StripeSCA].include? @payment.payment_method.class
+ end
+
+ def card_set?
+ @payment.source.is_a? Spree::CreditCard
+ end
+
+ def saved_credit_card
+ @order.user.default_card
+ end
+
+ def allow_charges?
+ @order.customer.allow_charges?
+ end
+
+ def use_saved_credit_card
+ @payment.update_attributes(source: saved_credit_card)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb
new file mode 100644
index 0000000000..ea4fbe5ce7
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ class StripeScaPaymentAuthorize
+ def initialize(order)
+ @order = order
+ @payment = OrderPaymentFinder.new(@order).last_pending_payment
+ end
+
+ def call!
+ return unless @payment&.checkout?
+
+ @payment.authorize!
+
+ @order.errors.add(:base, I18n.t('authorization_failure')) unless @payment.pending?
+
+ @payment
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/summarizer.rb b/engines/order_management/app/services/order_management/subscriptions/summarizer.rb
new file mode 100644
index 0000000000..0642e22044
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/summarizer.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# Used by for SubscriptionPlacementJob and SubscriptionConfirmJob to summarize the
+# result of automatic processing of subscriptions for the relevant shop owners.
+module OrderManagement
+ module Subscriptions
+ class Summarizer
+ def initialize
+ @summaries = {}
+ end
+
+ def record_order(order)
+ summary_for(order).record_order(order)
+ end
+
+ def record_success(order)
+ summary_for(order).record_success(order)
+ end
+
+ def record_issue(type, order, message = nil)
+ Rails.logger.info "Issue in Subscription Order #{order.id}: #{type}"
+ summary_for(order).record_issue(type, order, message)
+ end
+
+ def record_and_log_error(type, order)
+ return record_issue(type, order) unless order.errors.any?
+
+ error = "Subscription#{type.to_s.camelize}Error"
+ line1 = "#{error}: Cannot process order #{order.number} due to errors"
+ line2 = "Errors: #{order.errors.full_messages.join(', ')}"
+ Rails.logger.info("#{line1}\n#{line2}")
+ record_issue(type, order, line2)
+ end
+
+ def send_placement_summary_emails
+ @summaries.values.each do |summary|
+ SubscriptionMailer.placement_summary_email(summary).deliver
+ end
+ end
+
+ def send_confirmation_summary_emails
+ @summaries.values.each do |summary|
+ SubscriptionMailer.confirmation_summary_email(summary).deliver
+ end
+ end
+
+ private
+
+ def summary_for(order)
+ shop_id = order.distributor_id
+ @summaries[shop_id] ||= Summary.new(shop_id)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/summary.rb b/engines/order_management/app/services/order_management/subscriptions/summary.rb
new file mode 100644
index 0000000000..c37272c6d3
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/summary.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ class Summary
+ attr_reader :shop_id, :issues
+
+ def initialize(shop_id)
+ @shop_id = shop_id
+ @order_ids = []
+ @success_ids = []
+ @issues = {}
+ end
+
+ def record_order(order)
+ @order_ids << order.id
+ end
+
+ def record_success(order)
+ @success_ids << order.id
+ end
+
+ def record_issue(type, order, message)
+ issues[type] ||= {}
+ issues[type][order.id] = message
+ end
+
+ def order_count
+ @order_ids.count
+ end
+
+ def success_count
+ @success_ids.count
+ end
+
+ def issue_count
+ (@order_ids - @success_ids).count
+ end
+
+ def orders_affected_by(type)
+ case type
+ when :other then Spree::Order.where(id: unrecorded_ids)
+ else Spree::Order.where(id: issues[type].keys)
+ end
+ end
+
+ def unrecorded_ids
+ recorded_ids = issues.values.map(&:keys).flatten
+ @order_ids - @success_ids - recorded_ids
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/validator.rb b/engines/order_management/app/services/order_management/subscriptions/validator.rb
new file mode 100644
index 0000000000..a8bc6b3086
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/validator.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+# Encapsulation of all of the validation logic required for subscriptions
+# Public interface consists of #valid? method provided by ActiveModel::Validations
+# and #json_errors which compiles a serializable hash of errors
+module OrderManagement
+ module Subscriptions
+ class Validator
+ include ActiveModel::Naming
+ include ActiveModel::Conversion
+ include ActiveModel::Validations
+
+ attr_reader :subscription
+
+ validates :shop, :customer, :schedule, :shipping_method, :payment_method, presence: true
+ validates :bill_address, :ship_address, :begins_at, presence: true
+ validate :shipping_method_allowed?
+ validate :payment_method_allowed?
+ validate :payment_method_type_allowed?
+ validate :ends_at_after_begins_at?
+ validate :customer_allowed?
+ validate :schedule_allowed?
+ validate :credit_card_ok?
+ validate :subscription_line_items_present?
+ validate :requested_variants_available?
+
+ delegate :shop, :customer, :schedule, :shipping_method, :payment_method, to: :subscription
+ delegate :bill_address, :ship_address, :begins_at, :ends_at, to: :subscription
+ delegate :subscription_line_items, to: :subscription
+
+ def initialize(subscription)
+ @subscription = subscription
+ end
+
+ def json_errors
+ errors.messages.each_with_object({}) do |(key, value), errors|
+ errors[key] = value.map { |msg| build_msg_from(key, msg) }
+ end
+ end
+
+ private
+
+ def shipping_method_allowed?
+ return unless shipping_method
+ return if shipping_method.distributors.include?(shop)
+
+ errors.add(:shipping_method, :not_available_to_shop, shop: shop.name)
+ end
+
+ def payment_method_allowed?
+ return unless payment_method
+ return if payment_method.distributors.include?(shop)
+
+ errors.add(:payment_method, :not_available_to_shop, shop: shop.name)
+ end
+
+ def payment_method_type_allowed?
+ return unless payment_method
+ return if Subscription::ALLOWED_PAYMENT_METHOD_TYPES.include? payment_method.type
+
+ errors.add(:payment_method, :invalid_type)
+ end
+
+ def ends_at_after_begins_at?
+ # Only validates ends_at if it is present
+ return if begins_at.blank? || ends_at.blank?
+ return if ends_at > begins_at
+
+ errors.add(:ends_at, :after_begins_at)
+ end
+
+ def customer_allowed?
+ return unless customer
+ return if customer.enterprise == shop
+
+ errors.add(:customer, :does_not_belong_to_shop, shop: shop.name)
+ end
+
+ def schedule_allowed?
+ return unless schedule
+ return if schedule.coordinators.include?(shop)
+
+ errors.add(:schedule, :not_coordinated_by_shop, shop: shop.name)
+ end
+
+ def credit_card_ok?
+ return unless customer && payment_method
+ return unless stripe_payment_method?(payment_method)
+ return errors.add(:payment_method, :charges_not_allowed) unless customer.allow_charges
+ return if customer.user.andand.default_card.present?
+
+ errors.add(:payment_method, :no_default_card)
+ end
+
+ def stripe_payment_method?(payment_method)
+ payment_method.type == "Spree::Gateway::StripeConnect" ||
+ payment_method.type == "Spree::Gateway::StripeSCA"
+ end
+
+ def subscription_line_items_present?
+ return if subscription_line_items.reject(&:marked_for_destruction?).any?
+
+ errors.add(:subscription_line_items, :at_least_one_product)
+ end
+
+ def requested_variants_available?
+ subscription_line_items.each { |sli| verify_availability_of(sli.variant) }
+ end
+
+ def verify_availability_of(variant)
+ return if available_variant_ids.include? variant.id
+
+ name = "#{variant.product.name} - #{variant.full_name}"
+ errors.add(:subscription_line_items, :not_available, name: name)
+ end
+
+ def available_variant_ids
+ return @available_variant_ids if @available_variant_ids.present?
+
+ subscription_variant_ids = subscription_line_items.map(&:variant_id)
+ @available_variant_ids = OrderManagement::Subscriptions::VariantsList.eligible_variants(shop)
+ .where(id: subscription_variant_ids).pluck(:id)
+ end
+
+ def build_msg_from(key, msg)
+ return msg[1..-1] if msg.starts_with?("^")
+
+ errors.full_message(key, msg)
+ end
+ end
+ end
+end
diff --git a/engines/order_management/app/services/order_management/subscriptions/variants_list.rb b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb
new file mode 100644
index 0000000000..5c5a3fddb3
--- /dev/null
+++ b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: false
+
+module OrderManagement
+ module Subscriptions
+ class VariantsList
+ # Includes the following variants:
+ # - Variants of permitted producers
+ # - Variants of hub
+ # - Variants that are in outgoing exchanges where the hub is receiver
+ def self.eligible_variants(distributor)
+ variant_conditions = ["spree_products.supplier_id IN (?)",
+ permitted_producer_ids(distributor)]
+ exchange_variant_ids = outgoing_exchange_variant_ids(distributor)
+ if exchange_variant_ids.present?
+ variant_conditions[0] << " OR spree_variants.id IN (?)"
+ variant_conditions << exchange_variant_ids
+ end
+
+ Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions)
+ end
+
+ def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant)
+ scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules })
+ .where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor })
+ .merge(OrderCycle.not_closed)
+ scope = scope.where(schedules: { id: schedule })
+ scope.any?
+ end
+
+ def self.permitted_producer_ids(distributor)
+ other_permitted_producer_ids = EnterpriseRelationship.joins(:parent)
+ .permitting(distributor.id).with_permission(:add_to_order_cycle)
+ .merge(Enterprise.is_primary_producer)
+ .pluck(:parent_id)
+
+ other_permitted_producer_ids | [distributor.id]
+ end
+
+ def self.outgoing_exchange_variant_ids(distributor)
+ ExchangeVariant.select("DISTINCT exchange_variants.variant_id").joins(:exchange)
+ .where(exchanges: { incoming: false, receiver_id: distributor.id })
+ .pluck(:variant_id)
+ end
+ end
+ end
+end
diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml
similarity index 93%
rename from app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml
rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml
index 744097e9a5..0aee85d71e 100644
--- a/app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml
+++ b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml
@@ -1,4 +1,4 @@
-= form_for @report_parameters, as: :report, url: spree.admin_reports_enterprise_fee_summary_path, method: :post do |f|
+= form_for @report_parameters, as: :report, url: main_app.order_management_reports_enterprise_fee_summary_path, method: :post do |f|
.row.date-range-filter
.sixteen.columns.alpha
= label_tag nil, t(".date_range")
diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml
similarity index 87%
rename from app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml
rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml
index 4427c511ba..332253b143 100644
--- a/app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml
+++ b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml
@@ -13,7 +13,7 @@
- if @renderer.data_rows.empty?
%tr
- %td{colspan: @renderer.header.length}= t(:none)
+ %td{colspan: @renderer.header.length}= t('.none')
- else
%p.report__message
= t(".select_and_search")
diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/create.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml
similarity index 100%
rename from app/views/spree/admin/reports/enterprise_fee_summaries/create.html.haml
rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml
diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/new.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/new.html.haml
similarity index 100%
rename from app/views/spree/admin/reports/enterprise_fee_summaries/new.html.haml
rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/new.html.haml
diff --git a/engines/order_management/config/routes.rb b/engines/order_management/config/routes.rb
index e221867e7e..79706c635a 100644
--- a/engines/order_management/config/routes.rb
+++ b/engines/order_management/config/routes.rb
@@ -1,5 +1,5 @@
-Spree::Core::Engine.routes.prepend do
- namespace :admin do
+Openfoodnetwork::Application.routes.prepend do
+ namespace :order_management do
namespace :reports do
resource :enterprise_fee_summary, only: [:new, :create]
end
diff --git a/spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb b/engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb
similarity index 94%
rename from spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb
rename to engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb
index d9d8962f9b..3282bd7258 100644
--- a/spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb
+++ b/engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb
@@ -1,6 +1,6 @@
require "spec_helper"
-describe Spree::Admin::Reports::EnterpriseFeeSummariesController, type: :controller do
+describe OrderManagement::Reports::EnterpriseFeeSummariesController, type: :controller do
let(:report_klass) { OrderManagement::Reports::EnterpriseFeeSummary }
let!(:distributor) { create(:distributor_enterprise) }
@@ -76,6 +76,6 @@ describe Spree::Admin::Reports::EnterpriseFeeSummariesController, type: :control
end
def new_template_path
- "spree/admin/reports/enterprise_fee_summaries/new"
+ "order_management/reports/enterprise_fee_summaries/new"
end
end
diff --git a/spec/features/admin/reports/enterprise_fee_summaries_spec.rb b/engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb
similarity index 93%
rename from spec/features/admin/reports/enterprise_fee_summaries_spec.rb
rename to engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb
index 57a8de346e..7930ea75a3 100644
--- a/spec/features/admin/reports/enterprise_fee_summaries_spec.rb
+++ b/engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb
@@ -41,7 +41,7 @@ feature "enterprise fee summaries", js: true do
it "does not allow access to the report" do
visit spree.admin_reports_path
expect(page).to have_no_link(I18n.t("admin.reports.enterprise_fee_summary.name"))
- visit spree.new_admin_reports_enterprise_fee_summary_path
+ visit main_app.new_order_management_reports_enterprise_fee_summary_path
expect(page).to have_content(I18n.t("unauthorized"))
end
end
@@ -49,7 +49,7 @@ feature "enterprise fee summaries", js: true do
describe "smoke test for filters" do
before do
- visit spree.new_admin_reports_enterprise_fee_summary_path
+ visit main_app.new_order_management_reports_enterprise_fee_summary_path
end
context "when logged in as admin" do
@@ -80,7 +80,7 @@ feature "enterprise fee summaries", js: true do
describe "smoke test for generation of report based on permissions" do
before do
- visit spree.new_admin_reports_enterprise_fee_summary_path
+ visit main_app.new_order_management_reports_enterprise_fee_summary_path
end
context "when logged in as admin" do
@@ -138,7 +138,7 @@ feature "enterprise fee summaries", js: true do
let(:current_user) { create(:admin_user) }
before do
- visit spree.new_admin_reports_enterprise_fee_summary_path
+ visit main_app.new_order_management_reports_enterprise_fee_summary_path
end
it "generates file with data for selected order cycle" do
@@ -155,6 +155,6 @@ feature "enterprise fee summaries", js: true do
end
def i18n_scope
- "spree.admin.reports.enterprise_fee_summaries"
+ "order_management.reports.enterprise_fee_summaries"
end
end
diff --git a/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb b/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb
new file mode 100644
index 0000000000..b62267b714
--- /dev/null
+++ b/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ describe ProxyOrderSyncer, performance: true do
+ let(:start) { Time.zone.now.beginning_of_day }
+ let!(:schedule) { create(:schedule, order_cycles: order_cycles) }
+
+ let!(:order_cycles) do
+ Array.new(10) do |i|
+ create(:simple_order_cycle, orders_open_at: start + i.days,
+ orders_close_at: start + (i + 1).days )
+ end
+ end
+
+ let!(:subscriptions) do
+ Array.new(150) do |_i|
+ create(:subscription, schedule: schedule, begins_at: start, ends_at: start + 10.days)
+ end
+ Subscription.where(schedule_id: schedule)
+ end
+
+ context "measuring performance for initialisation" do
+ it "reports the average run time for adding 10 OCs to 150 subscriptions" do
+ expect(ProxyOrder.count).to be 0
+ times = []
+ 10.times do
+ syncer = ProxyOrderSyncer.new(subscriptions.reload)
+
+ t1 = Time.zone.now
+ syncer.sync!
+ t2 = Time.zone.now
+ diff = t2 - t1
+ times << diff
+ puts diff.round(2)
+
+ expect(ProxyOrder.count).to be 1500
+ ProxyOrder.destroy_all
+ end
+ puts "AVG: #{(times.sum / times.count).round(2)}"
+ end
+ end
+
+ context "measuring performance for removal" do
+ it "reports the average run time for removing 8 OCs from 150 subscriptions" do
+ times = []
+ 10.times do
+ syncer = ProxyOrderSyncer.new(subscriptions.reload)
+ syncer.sync!
+ expect(ProxyOrder.count).to be 1500
+ subscriptions.update_all(begins_at: start + 8.days + 1.minute)
+ syncer = ProxyOrderSyncer.new(subscriptions.reload)
+
+ t1 = Time.zone.now
+ syncer.sync!
+ t2 = Time.zone.now
+ diff = t2 - t1
+ times << diff
+ puts diff.round(2)
+
+ expect(ProxyOrder.count).to be 300
+ subscriptions.update_all(begins_at: start)
+ end
+ puts "AVG: #{(times.sum / times.count).round(2)}"
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb
index 5b9c62b03c..1bd591e021 100644
--- a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb
+++ b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb
@@ -5,7 +5,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::Renderers::HtmlRenderer
let!(:permissions) { report_klass::Permissions.new(current_user) }
let!(:parameters) { report_klass::Parameters.new }
- let!(:controller) { Spree::Admin::Reports::EnterpriseFeeSummariesController.new }
+ let!(:controller) { OrderManagement::Reports::EnterpriseFeeSummariesController.new }
let!(:service) { report_klass::ReportService.new(permissions, parameters) }
let!(:renderer) { described_class.new(service) }
diff --git a/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb
new file mode 100644
index 0000000000..14b5a8c041
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ describe Count do
+ let(:oc1) { create(:simple_order_cycle) }
+ let(:oc2) { create(:simple_order_cycle) }
+ let(:subscriptions_count) { Count.new(order_cycles) }
+
+ describe "#for" do
+ context "when the collection has not been set" do
+ let(:order_cycles) { nil }
+ it "returns 0" do
+ expect(subscriptions_count.for(oc1.id)).to eq 0
+ end
+ end
+
+ context "when the collection has been set" do
+ let(:order_cycles) { OrderCycle.where(id: [oc1]) }
+ let!(:po1) { create(:proxy_order, order_cycle: oc1) }
+ let!(:po2) { create(:proxy_order, order_cycle: oc1) }
+ let!(:po3) { create(:proxy_order, order_cycle: oc2) }
+
+ context "but the requested id is not present in the list of order cycles provided" do
+ it "returns 0" do
+ # Note that po3 applies to oc2, but oc2 in not in the collection
+ expect(subscriptions_count.for(oc2.id)).to eq 0
+ end
+ end
+
+ context "and the requested id is present in the list of order cycles provided" do
+ it "returns a count of active proxy orders associated with the requested order cycle" do
+ expect(subscriptions_count.for(oc1.id)).to eq 2
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb
new file mode 100644
index 0000000000..e8fe7bf957
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb
@@ -0,0 +1,171 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ describe Estimator do
+ describe "estimating prices for subscription line items" do
+ let!(:subscription) { create(:subscription, with_items: true) }
+ let!(:sli1) { subscription.subscription_line_items.first }
+ let!(:sli2) { subscription.subscription_line_items.second }
+ let!(:sli3) { subscription.subscription_line_items.third }
+ let(:estimator) { Estimator.new(subscription) }
+
+ before do
+ sli1.update_attributes(price_estimate: 4.0)
+ sli2.update_attributes(price_estimate: 5.0)
+ sli3.update_attributes(price_estimate: 6.0)
+ sli1.variant.update_attributes(price: 1.0)
+ sli2.variant.update_attributes(price: 2.0)
+ sli3.variant.update_attributes(price: 3.0)
+
+ # Simulating assignment of attrs from params
+ sli1.assign_attributes(price_estimate: 7.0)
+ sli2.assign_attributes(price_estimate: 8.0)
+ sli3.assign_attributes(price_estimate: 9.0)
+ end
+
+ context "when a insufficient information exists to calculate price estimates" do
+ before do
+ # This might be because a shop has not been assigned yet, or no
+ # current or future order cycles exist for the schedule
+ allow(estimator).to receive(:fee_calculator) { nil }
+ end
+
+ it "resets the price estimates for all items" do
+ estimator.estimate!
+ expect(sli1.price_estimate).to eq 4.0
+ expect(sli2.price_estimate).to eq 5.0
+ expect(sli3.price_estimate).to eq 6.0
+ end
+ end
+
+ context "when sufficient information to calculate price estimates exists" do
+ let(:fee_calculator) { instance_double(OpenFoodNetwork::EnterpriseFeeCalculator) }
+
+ before do
+ allow(estimator).to receive(:fee_calculator) { fee_calculator }
+ allow(fee_calculator).to receive(:indexed_fees_for).with(sli1.variant) { 1.0 }
+ allow(fee_calculator).to receive(:indexed_fees_for).with(sli2.variant) { 0.0 }
+ allow(fee_calculator).to receive(:indexed_fees_for).with(sli3.variant) { 3.0 }
+ end
+
+ context "when no variant overrides apply" do
+ it "recalculates price_estimates based on variant prices and associated fees" do
+ estimator.estimate!
+ expect(sli1.price_estimate).to eq 2.0
+ expect(sli2.price_estimate).to eq 2.0
+ expect(sli3.price_estimate).to eq 6.0
+ end
+ end
+
+ context "when variant overrides apply" do
+ let!(:override1) {
+ create(:variant_override, hub: subscription.shop, variant: sli1.variant, price: 1.2)
+ }
+ let!(:override2) {
+ create(:variant_override, hub: subscription.shop, variant: sli2.variant, price: 2.3)
+ }
+
+ it "recalculates price_estimates based on override prices and associated fees" do
+ estimator.estimate!
+ expect(sli1.price_estimate).to eq 2.2
+ expect(sli2.price_estimate).to eq 2.3
+ expect(sli3.price_estimate).to eq 6.0
+ end
+ end
+ end
+ end
+
+ describe "updating estimates for shipping and payment fees" do
+ let(:subscription) {
+ create(:subscription, with_items: true,
+ payment_method: payment_method,
+ shipping_method: shipping_method)
+ }
+ let!(:sli1) { subscription.subscription_line_items.first }
+ let!(:sli2) { subscription.subscription_line_items.second }
+ let!(:sli3) { subscription.subscription_line_items.third }
+ let(:estimator) { OrderManagement::Subscriptions::Estimator.new(subscription) }
+
+ before do
+ allow(estimator).to receive(:assign_price_estimates)
+ sli1.update_attributes(price_estimate: 4.0)
+ sli2.update_attributes(price_estimate: 5.0)
+ sli3.update_attributes(price_estimate: 6.0)
+ end
+
+ context "using flat rate calculators" do
+ let(:shipping_method) {
+ create(:shipping_method,
+ calculator: Spree::Calculator::FlatRate.new(preferred_amount: 12.34))
+ }
+ let(:payment_method) {
+ create(:payment_method,
+ calculator: Spree::Calculator::FlatRate.new(preferred_amount: 9.12))
+ }
+
+ it "calculates fees based on the rates provided" do
+ estimator.estimate!
+ expect(subscription.shipping_fee_estimate.to_f).to eq 12.34
+ expect(subscription.payment_fee_estimate.to_f).to eq 9.12
+ end
+ end
+
+ context "using flat percent item total calculators" do
+ let(:shipping_method) {
+ create(:shipping_method,
+ calculator: Spree::Calculator::FlatPercentItemTotal.new(
+ preferred_flat_percent: 10
+ ))
+ }
+ let(:payment_method) {
+ create(:payment_method,
+ calculator: Spree::Calculator::FlatPercentItemTotal.new(
+ preferred_flat_percent: 20
+ ))
+ }
+
+ it "calculates fees based on the estimated item total and percentage provided" do
+ estimator.estimate!
+ expect(subscription.shipping_fee_estimate.to_f).to eq 1.5
+ expect(subscription.payment_fee_estimate.to_f).to eq 3.0
+ end
+ end
+
+ context "using flat percent per item calculators" do
+ let(:shipping_method) {
+ create(:shipping_method,
+ calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 5))
+ }
+ let(:payment_method) {
+ create(:payment_method,
+ calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 10))
+ }
+
+ it "calculates fees based on the estimated item prices and percentage provided" do
+ estimator.estimate!
+ expect(subscription.shipping_fee_estimate.to_f).to eq 0.75
+ expect(subscription.payment_fee_estimate.to_f).to eq 1.5
+ end
+ end
+
+ context "using per item calculators" do
+ let(:shipping_method) {
+ create(:shipping_method,
+ calculator: Spree::Calculator::PerItem.new(preferred_amount: 1.2))
+ }
+ let(:payment_method) {
+ create(:payment_method,
+ calculator: Spree::Calculator::PerItem.new(preferred_amount: 0.3))
+ }
+
+ it "calculates fees based on the number of items and rate provided" do
+ estimator.estimate!
+ expect(subscription.shipping_fee_estimate.to_f).to eq 3.6
+ expect(subscription.payment_fee_estimate.to_f).to eq 0.9
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb
new file mode 100644
index 0000000000..a86dbac0e9
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module OrderManagement
+ module Subscriptions
+ describe Form do
+ describe "creating a new subscription" do
+ let!(:shop) { create(:distributor_enterprise) }
+ let!(:customer) { create(:customer, enterprise: shop) }
+ let!(:product1) { create(:product, supplier: shop) }
+ let!(:product2) { create(:product, supplier: shop) }
+ let!(:product3) { create(:product, supplier: shop) }
+ let!(:variant1) {
+ create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: [])
+ }
+ let!(:variant2) {
+ create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: [])
+ }
+ let!(:variant3) {
+ create(:variant, product: product2, unit_value: '1000',
+ price: 2.50, option_values: [], on_hand: 1)
+ }
+ let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
+ let!(:order_cycle1) {
+ create(:simple_order_cycle, coordinator: shop,
+ orders_open_at: 9.days.ago,
+ orders_close_at: 2.days.ago)
+ }
+ let!(:order_cycle2) {
+ create(:simple_order_cycle, coordinator: shop,
+ orders_open_at: 2.days.ago,
+ orders_close_at: 5.days.from_now)
+ }
+ let!(:order_cycle3) {
+ create(:simple_order_cycle, coordinator: shop,
+ orders_open_at: 5.days.from_now,
+ orders_close_at: 12.days.from_now)
+ }
+ let!(:order_cycle4) {
+ create(:simple_order_cycle, coordinator: shop,
+ orders_open_at: 12.days.from_now,
+ orders_close_at: 19.days.from_now)
+ }
+ let!(:outgoing_exchange1) {
+ order_cycle1.exchanges.create(sender: shop,
+ receiver: shop,
+ variants: [variant1, variant2, variant3],
+ enterprise_fees: [enterprise_fee])
+ }
+ let!(:outgoing_exchange2) {
+ order_cycle2.exchanges.create(sender: shop,
+ receiver: shop,
+ variants: [variant1, variant2, variant3],
+ enterprise_fees: [enterprise_fee])
+ }
+ let!(:outgoing_exchange3) {
+ order_cycle3.exchanges.create(sender: shop,
+ receiver: shop,
+ variants: [variant1, variant3],
+ enterprise_fees: [])
+ }
+ let!(:outgoing_exchange4) {
+ order_cycle4.exchanges.create(sender: shop,
+ receiver: shop,
+ variants: [variant1, variant2, variant3],
+ enterprise_fees: [enterprise_fee])
+ }
+ let!(:schedule) {
+ create(:schedule, order_cycles: [order_cycle1, order_cycle2, order_cycle3, order_cycle4])
+ }
+ let!(:payment_method) { create(:payment_method, distributors: [shop]) }
+ let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
+ let!(:address) { create(:address) }
+ let(:subscription) { Subscription.new }
+
+ let!(:params) {
+ {
+ shop_id: shop.id,
+ customer_id: customer.id,
+ schedule_id: schedule.id,
+ bill_address_attributes: address.clone.attributes,
+ ship_address_attributes: address.clone.attributes,
+ payment_method_id: payment_method.id,
+ shipping_method_id: shipping_method.id,
+ begins_at: 4.days.ago,
+ ends_at: 14.days.from_now,
+ subscription_line_items_attributes: [
+ { variant_id: variant1.id, quantity: 1, price_estimate: 7.0 },
+ { variant_id: variant2.id, quantity: 2, price_estimate: 8.0 },
+ { variant_id: variant3.id, quantity: 3, price_estimate: 9.0 }
+ ]
+ }
+ }
+
+ let(:form) { OrderManagement::Subscriptions::Form.new(subscription, params) }
+
+ it "creates orders for each order cycle in the schedule" do
+ expect(form.save).to be true
+
+ expect(subscription.proxy_orders.count).to be 2
+ expect(subscription.subscription_line_items.count).to be 3
+ expect(subscription.subscription_line_items[0].price_estimate).to eq 13.75
+ expect(subscription.subscription_line_items[1].price_estimate).to eq 7.75
+ expect(subscription.subscription_line_items[2].price_estimate).to eq 4.25
+
+ # This order cycle has already closed, so no order is initialized
+ proxy_order1 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle1.id)
+ expect(proxy_order1).to be nil
+
+ # Currently open order cycle, closing after begins_at and before ends_at
+ proxy_order2 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle2.id)
+ expect(proxy_order2).to be_a ProxyOrder
+ order2 = proxy_order2.initialise_order!
+ expect(order2.line_items.count).to eq 3
+ expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3
+ expect(order2.shipments.count).to eq 1
+ expect(order2.shipments.first.shipping_method).to eq shipping_method
+ expect(order2.payments.count).to eq 1
+ expect(order2.payments.first.payment_method).to eq payment_method
+ expect(order2.payments.first.state).to eq 'checkout'
+ expect(order2.total).to eq 42
+ expect(order2.completed?).to be false
+
+ # Future order cycle, closing after begins_at and before ends_at
+ # Adds line items for variants that aren't yet available from the order cycle
+ proxy_order3 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle3.id)
+ expect(proxy_order3).to be_a ProxyOrder
+ order3 = proxy_order3.initialise_order!
+ expect(order3).to be_a Spree::Order
+ expect(order3.line_items.count).to eq 3
+ expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3
+ expect(order3.shipments.count).to eq 1
+ expect(order3.shipments.first.shipping_method).to eq shipping_method
+ expect(order3.payments.count).to eq 1
+ expect(order3.payments.first.payment_method).to eq payment_method
+ expect(order3.payments.first.state).to eq 'checkout'
+ expect(order3.total).to eq 31.50
+ expect(order3.completed?).to be false
+
+ # Future order cycle closing after ends_at
+ proxy_order4 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle4.id)
+ expect(proxy_order4).to be nil
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb
new file mode 100644
index 0000000000..32bf3874d0
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module OrderManagement
+ module Subscriptions
+ describe PaymentSetup do
+ let(:order) { create(:order) }
+ let(:payment_setup) { OrderManagement::Subscriptions::PaymentSetup.new(order) }
+
+ describe "#call!" do
+ let!(:payment){ create(:payment, amount: 10) }
+
+ context "when no pending payments are present" do
+ let(:payment_method) { create(:payment_method) }
+ let(:subscription) { double(:subscription, payment_method_id: payment_method.id) }
+
+ before do
+ allow(order).to receive(:pending_payments).once { [] }
+ allow(order).to receive(:outstanding_balance) { 5 }
+ allow(order).to receive(:subscription) { subscription }
+ end
+
+ it "creates a new payment on the order" do
+ expect{ payment_setup.call! }.to change(Spree::Payment, :count).by(1)
+ expect(order.payments.first.amount).to eq 5
+ end
+ end
+
+ context "when a payment is present" do
+ before { allow(order).to receive(:pending_payments).once { [payment] } }
+
+ context "when the payment total doesn't match the outstanding balance on the order" do
+ before { allow(order).to receive(:outstanding_balance) { 5 } }
+ it "updates the payment total to reflect the outstanding balance" do
+ expect{ payment_setup.call! }.to change(payment, :amount).from(10).to(5)
+ end
+ end
+
+ context "when the payment total matches the outstanding balance on the order" do
+ before { allow(order).to receive(:outstanding_balance) { 10 } }
+
+ it "does nothing" do
+ expect{ payment_setup.call! }.to_not change(payment, :amount).from(10)
+ end
+ end
+ end
+
+ context "when more that one payment exists on the order" do
+ let!(:payment1) { create(:payment, order: order) }
+ let!(:payment2) { create(:payment, order: order) }
+
+ before do
+ allow(order).to receive(:outstanding_balance) { 7 }
+ allow(order).to receive(:pending_payments).once { [payment1, payment2] }
+ end
+
+ it "updates the amount of the last payment to reflect the outstanding balance" do
+ payment_setup.call!
+ expect(payment1.amount).to eq 45.75
+ expect(payment2.amount).to eq 7
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb
new file mode 100644
index 0000000000..501f6fa67e
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb
@@ -0,0 +1,437 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ describe ProxyOrderSyncer do
+ describe "initialization" do
+ let!(:subscription) { create(:subscription) }
+
+ it "raises an error when initialized with an object
+ that is not a Subscription or an ActiveRecord::Relation" do
+ expect{ ProxyOrderSyncer.new(subscription) }.to_not raise_error
+ expect{ ProxyOrderSyncer.new(Subscription.where(id: subscription.id)) }.to_not raise_error
+ expect{ ProxyOrderSyncer.new("something") }.to raise_error RuntimeError
+ end
+ end
+
+ describe "#sync!" do
+ let(:now) { Time.zone.now }
+ let(:schedule) { create(:schedule) }
+ let(:closed_oc) { # Closed
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now - 1.minute,
+ orders_close_at: now)
+ }
+ let(:open_oc_closes_before_begins_at_oc) { # Open, but closes before begins at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now - 1.minute,
+ orders_close_at: now + 59.seconds)
+ }
+ let(:open_oc) { # Open & closes between begins at and ends at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now - 1.minute,
+ orders_close_at: now + 90.seconds)
+ }
+ let(:upcoming_closes_before_begins_at_oc) { # Upcoming, but closes before begins at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now + 30.seconds,
+ orders_close_at: now + 59.seconds)
+ }
+ let(:upcoming_closes_on_begins_at_oc) { # Upcoming & closes on begins at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now + 30.seconds,
+ orders_close_at: now + 1.minute)
+ }
+ let(:upcoming_closes_on_ends_at_oc) { # Upcoming & closes on ends at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now + 30.seconds,
+ orders_close_at: now + 2.minutes)
+ }
+ let(:upcoming_closes_after_ends_at_oc) { # Upcoming & closes after ends at
+ create(:simple_order_cycle, schedules: [schedule],
+ orders_open_at: now + 30.seconds,
+ orders_close_at: now + 121.seconds)
+ }
+ let(:subscription) {
+ build(:subscription, schedule: schedule,
+ begins_at: now + 1.minute,
+ ends_at: now + 2.minutes)
+ }
+ let(:proxy_orders) { subscription.reload.proxy_orders }
+ let(:order_cycles) { proxy_orders.map(&:order_cycle) }
+ let(:syncer) { ProxyOrderSyncer.new(subscription) }
+
+ context "when the subscription is not persisted" do
+ before do
+ oc # Ensure oc is created before we attempt to sync
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
+ end
+
+ context "and the schedule includes a closed oc (ie. closed before opens_at)" do
+ let(:oc) { closed_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule includes an open oc that closes before begins_at" do
+ let(:oc) { open_oc_closes_before_begins_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule has an open OC that closes between begins_at and ends_at" do
+ let(:oc) { open_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes before begins_at" do
+ let(:oc) { upcoming_closes_before_begins_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes on begins_at" do
+ let(:oc) { upcoming_closes_on_begins_at_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes after ends_at" do
+ let(:oc) { upcoming_closes_on_ends_at_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes after ends_at" do
+ let(:oc) { upcoming_closes_after_ends_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+ end
+
+ context "when the subscription is persisted" do
+ before { expect(subscription.save!).to be true }
+
+ context "when a proxy order exists" do
+ let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: oc) }
+
+ context "for an oc included in the relevant schedule" do
+ context "and the proxy order has already been placed" do
+ before { proxy_order.update_attributes(placed_at: 5.minutes.ago) }
+
+ context "the oc is closed (ie. closed before opens_at)" do
+ let(:oc) { closed_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the schedule includes an open oc that closes before begins_at" do
+ let(:oc) { open_oc_closes_before_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is open and closes between begins_at and ends_at" do
+ let(:oc) { open_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes before begins_at" do
+ let(:oc) { upcoming_closes_before_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on begins_at" do
+ let(:oc) { upcoming_closes_on_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on ends_at" do
+ let(:oc) { upcoming_closes_on_ends_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes after ends_at" do
+ let(:oc) { upcoming_closes_after_ends_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+ end
+
+ context "and the proxy order has not already been placed" do
+ context "the oc is closed (ie. closed before opens_at)" do
+ let(:oc) { closed_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the schedule includes an open oc that closes before begins_at" do
+ let(:oc) { open_oc_closes_before_begins_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is open and closes between begins_at and ends_at" do
+ let(:oc) { open_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes before begins_at" do
+ let(:oc) { upcoming_closes_before_begins_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on begins_at" do
+ let(:oc) { upcoming_closes_on_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on ends_at" do
+ let(:oc) { upcoming_closes_on_ends_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes after ends_at" do
+ let(:oc) { upcoming_closes_after_ends_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+ end
+ end
+
+ context "for an oc not included in the relevant schedule" do
+ let!(:proxy_order) {
+ create(:proxy_order, subscription: subscription, order_cycle: open_oc)
+ }
+ before do
+ open_oc.schedule_ids = []
+ expect(open_oc.save!).to be true
+ end
+
+ context "and the proxy order has already been placed" do
+ before { proxy_order.update_attributes(placed_at: 5.minutes.ago) }
+
+ context "the oc is closed (ie. closed before opens_at)" do
+ let(:oc) { closed_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the schedule includes an open oc that closes before begins_at" do
+ let(:oc) { open_oc_closes_before_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is open and closes between begins_at and ends_at" do
+ let(:oc) { open_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes before begins_at" do
+ let(:oc) { upcoming_closes_before_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on begins_at" do
+ let(:oc) { upcoming_closes_on_begins_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on ends_at" do
+ let(:oc) { upcoming_closes_on_ends_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes after ends_at" do
+ let(:oc) { upcoming_closes_after_ends_at_oc }
+ it "keeps the proxy order" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
+ expect(proxy_orders).to include proxy_order
+ end
+ end
+ end
+
+ context "and the proxy order has not already been placed" do
+ # This shouldn't really happen, but it is possible
+ context "the oc is closed (ie. closed before opens_at)" do
+ let(:oc) { closed_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ # This shouldn't really happen, but it is possible
+ context "and the oc is open and closes between begins_at and ends_at" do
+ let(:oc) { open_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes before begins_at" do
+ let(:oc) { upcoming_closes_before_begins_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on begins_at" do
+ let(:oc) { upcoming_closes_on_begins_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes on ends_at" do
+ let(:oc) { upcoming_closes_on_ends_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+
+ context "and the oc is upcoming and closes after ends_at" do
+ let(:oc) { upcoming_closes_after_ends_at_oc }
+ it "removes the proxy order" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
+ expect(proxy_orders).to_not include proxy_order
+ end
+ end
+ end
+ end
+ end
+
+ context "when a proxy order does not exist" do
+ context "and the schedule includes a closed oc (ie. closed before opens_at)" do
+ let!(:oc) { closed_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule includes an open oc that closes before begins_at" do
+ let(:oc) { open_oc_closes_before_begins_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule has an open oc that closes between begins_at and ends_at" do
+ let!(:oc) { open_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes before begins_at" do
+ let!(:oc) { upcoming_closes_before_begins_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes on begins_at" do
+ let!(:oc) { upcoming_closes_on_begins_at_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes on ends_at" do
+ let!(:oc) { upcoming_closes_on_ends_at_oc }
+ it "creates a new proxy order for that oc" do
+ expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
+ expect(order_cycles).to include oc
+ end
+ end
+
+ context "and the schedule includes upcoming oc that closes after ends_at" do
+ let!(:oc) { upcoming_closes_after_ends_at_oc }
+ it "does not create a new proxy order for that oc" do
+ expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
+ expect(order_cycles).to_not include oc
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb
new file mode 100644
index 0000000000..c928ddd95b
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module OrderManagement
+ module Subscriptions
+ describe StripePaymentSetup do
+ let(:order) { create(:order) }
+ let(:payment_setup) { OrderManagement::Subscriptions::StripePaymentSetup.new(order) }
+
+ describe "#call!" do
+ context "when no pending payments are present" do
+ before do
+ allow(order).to receive(:pending_payments).once { [] }
+ end
+
+ it "does nothing" do
+ expect(payment_setup.call!).to eq nil
+ end
+ end
+
+ context "when a payment is present" do
+ let(:payment) { create(:payment, payment_method: payment_method, amount: 10) }
+
+ before { allow(order).to receive(:pending_payments).once { [payment] } }
+
+ context "when the payment method is not a stripe payment method" do
+ let(:payment_method) { create(:payment_method) }
+
+ it "returns the pending payment with no change" do
+ expect(payment).to_not receive(:update_attributes)
+ expect(payment_setup.call!).to eq payment
+ end
+ end
+
+ context "when the payment method is a stripe payment method" do
+ let(:payment_method) { create(:stripe_payment_method) }
+
+ context "and the card is already set (the payment source is a credit card)" do
+ it "returns the pending payment with no change" do
+ expect(payment).to_not receive(:update_attributes)
+ expect(payment_setup.call!).to eq payment
+ end
+ end
+
+ context "and the card is not set (the payment source is not a credit card)" do
+ before { payment.update_attribute :source, nil }
+
+ context "and no default credit card has been saved by the customer" do
+ before do
+ allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) }
+ end
+
+ it "adds an error to the order and does not update the payment" do
+ payment_setup.call!
+
+ expect(payment).to_not receive(:update_attributes)
+ expect(payment_setup.call!).to eq payment
+ expect(order.errors[:base].first).to eq "There are no authorised "\
+ "credit cards available to charge"
+ end
+ end
+
+ context "and a default credit card has been saved by the customer" do
+ let(:saved_credit_card) { create(:credit_card) }
+
+ before do
+ allow(order).to receive(:user) {
+ instance_double(Spree::User, default_card: saved_credit_card)
+ }
+ end
+
+ context "but the customer has not authorised the shop to charge credit cards" do
+ before do
+ allow(order).to receive(:customer) {
+ instance_double(Customer, allow_charges?: false)
+ }
+ end
+
+ it "adds an error to the order and does not update the payment" do
+ payment_setup.call!
+
+ expect(payment).to_not receive(:update_attributes)
+ expect(payment_setup.call!).to eq payment
+ expect(order.errors[:base].first).to eq "There are no authorised "\
+ "credit cards available to charge"
+ end
+ end
+
+ context "and the customer has authorised the shop to charge credit cards" do
+ before do
+ allow(order).to receive(:customer) {
+ instance_double(Customer, allow_charges?: true)
+ }
+ end
+
+ it "uses the saved credit card as the source for the payment" do
+ payment_setup.call!
+ expect(payment.source).to eq saved_credit_card
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb
new file mode 100644
index 0000000000..17ece20be4
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module OrderManagement
+ module Subscriptions
+ describe StripeScaPaymentAuthorize do
+ let(:order) { create(:order) }
+ let(:payment_authorize) {
+ OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order)
+ }
+
+ describe "#call!" do
+ context "when no pending payments are present" do
+ before { allow(order).to receive(:pending_payments).once { [] } }
+
+ it "does nothing" do
+ expect(payment_authorize.call!).to eq nil
+ end
+ end
+
+ context "when a payment is present" do
+ let(:payment) { create(:payment, amount: 10) }
+
+ before { allow(order).to receive(:pending_payments).once { [payment] } }
+
+ context "in a state that is not checkout" do
+ before { payment.state = "processing" }
+
+ it "does nothing" do
+ payment_authorize.call!
+
+ expect(payment.state).to eq "processing"
+ expect(order.errors.size).to eq 0
+ end
+ end
+
+ context "in the checkout state" do
+ before { payment.state = "checkout" }
+
+ context "and payment authorize moves the payment state to pending" do
+ before { expect(payment).to receive(:authorize!) { payment.state = "pending" } }
+
+ it "does nothing" do
+ payment_authorize.call!
+
+ expect(order.errors.size).to eq 0
+ end
+ end
+
+ context "and payment authorize does not move the payment state to pending" do
+ before { allow(payment).to receive(:authorize!) { payment.state = "failed" } }
+
+ it "adds an error to the order indicating authorization failure" do
+ payment_authorize.call!
+
+ expect(order.errors[:base].first).to eq "Authorization Failure"
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb
new file mode 100644
index 0000000000..09013c204c
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module OrderManagement
+ module Subscriptions
+ describe Summarizer do
+ let(:order) { create(:order) }
+ let(:summarizer) { OrderManagement::Subscriptions::Summarizer.new }
+
+ before { allow(Rails.logger).to receive(:info) }
+
+ describe "#summary_for" do
+ let(:order) { double(:order, distributor_id: 123) }
+
+ context "when a summary for the order's distributor doesn't already exist" do
+ it "initializes a new summary object, and returns it" do
+ expect(summarizer.instance_variable_get(:@summaries).count).to be 0
+ summary = summarizer.__send__(:summary_for, order)
+ expect(summary.shop_id).to be 123
+ expect(summarizer.instance_variable_get(:@summaries).count).to be 1
+ end
+ end
+
+ context "when a summary for the order's distributor already exists" do
+ let(:summary) { double(:summary) }
+
+ before do
+ summarizer.instance_variable_set(:@summaries, 123 => summary)
+ end
+
+ it "returns the existing summary object" do
+ expect(summarizer.instance_variable_get(:@summaries).count).to be 1
+ expect(summarizer.__send__(:summary_for, order)).to eq summary
+ expect(summarizer.instance_variable_get(:@summaries).count).to be 1
+ end
+ end
+ end
+
+ describe "recording events" do
+ let(:order) { double(:order) }
+ let(:summary) { double(:summary) }
+ before { allow(summarizer).to receive(:summary_for).with(order) { summary } }
+
+ describe "#record_order" do
+ it "requests a summary for the order and calls #record_order on it" do
+ expect(summary).to receive(:record_order).with(order).once
+ summarizer.record_order(order)
+ end
+ end
+
+ describe "#record_success" do
+ it "requests a summary for the order and calls #record_success on it" do
+ expect(summary).to receive(:record_success).with(order).once
+ summarizer.record_success(order)
+ end
+ end
+
+ describe "#record_issue" do
+ it "requests a summary for the order and calls #record_issue on it" do
+ expect(order).to receive(:id)
+ expect(summary).to receive(:record_issue).with(:type, order, "message").once
+ summarizer.record_issue(:type, order, "message")
+ end
+ end
+
+ describe "#record_and_log_error" do
+ before do
+ allow(order).to receive(:number) { "123" }
+ end
+
+ context "when errors exist on the order" do
+ before do
+ allow(order).to receive(:errors) {
+ double(:errors, any?: true, full_messages: ["Some error"])
+ }
+ end
+
+ it "sends error info to rails logger and calls #record_issue with an error message" do
+ expect(summarizer).to receive(:record_issue).with(:processing,
+ order, "Errors: Some error")
+ summarizer.record_and_log_error(:processing, order)
+ end
+ end
+
+ context "when no errors exist on the order" do
+ before do
+ allow(order).to receive(:errors) { double(:errors, any?: false) }
+ end
+
+ it "falls back to calling record_issue" do
+ expect(summarizer).to receive(:record_issue).with(:processing, order)
+ summarizer.record_and_log_error(:processing, order)
+ end
+ end
+ end
+ end
+
+ describe "#send_placement_summary_emails" do
+ let(:summary1) { double(:summary) }
+ let(:summary2) { double(:summary) }
+ let(:summaries) { { 1 => summary1, 2 => summary2 } }
+ let(:mail_mock) { double(:mail, deliver: true) }
+
+ before do
+ summarizer.instance_variable_set(:@summaries, summaries)
+ end
+
+ it "sends a placement summary email for each summary" do
+ expect(SubscriptionMailer).to receive(:placement_summary_email).twice { mail_mock }
+ summarizer.send_placement_summary_emails
+ end
+ end
+
+ describe "#send_confirmation_summary_emails" do
+ let(:summary1) { double(:summary) }
+ let(:summary2) { double(:summary) }
+ let(:summaries) { { 1 => summary1, 2 => summary2 } }
+ let(:mail_mock) { double(:mail, deliver: true) }
+
+ before do
+ summarizer.instance_variable_set(:@summaries, summaries)
+ end
+
+ it "sends a placement summary email for each summary" do
+ expect(SubscriptionMailer).to receive(:confirmation_summary_email).twice { mail_mock }
+ summarizer.send_confirmation_summary_emails
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb
new file mode 100644
index 0000000000..5e6360c542
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+module OrderManagement
+ module Subscriptions
+ describe Summary do
+ let(:summary) { OrderManagement::Subscriptions::Summary.new(123) }
+
+ describe "#initialize" do
+ it "initializes instance variables: shop_id, order_count, success_count and issues" do
+ expect(summary.shop_id).to be 123
+ expect(summary.order_count).to be 0
+ expect(summary.success_count).to be 0
+ expect(summary.issues).to be_a Hash
+ end
+ end
+
+ describe "#record_order" do
+ let(:order) { double(:order, id: 37) }
+ it "adds the order id to the order_ids array" do
+ summary.record_order(order)
+ expect(summary.instance_variable_get(:@order_ids)).to eq [order.id]
+ end
+ end
+
+ describe "#record_success" do
+ let(:order) { double(:order, id: 37) }
+ it "adds the order id to the success_ids array" do
+ summary.record_success(order)
+ expect(summary.instance_variable_get(:@success_ids)).to eq [order.id]
+ end
+ end
+
+ describe "#record_issue" do
+ let(:order) { double(:order, id: 1) }
+
+ context "when no issues of the same type have been recorded yet" do
+ it "adds a new type to the issues hash, and stores a new issue against it" do
+ summary.record_issue(:some_type, order, "message")
+ expect(summary.issues.keys).to include :some_type
+ expect(summary.issues[:some_type][order.id]).to eq "message"
+ end
+ end
+
+ context "when an issue of the same type has already been recorded" do
+ let(:existing_issue) { double(:existing_issue) }
+
+ before { summary.issues[:some_type] = [existing_issue] }
+
+ it "stores a new issue against the existing type" do
+ summary.record_issue(:some_type, order, "message")
+ expect(summary.issues[:some_type]).to include existing_issue
+ expect(summary.issues[:some_type][order.id]).to eq "message"
+ end
+ end
+ end
+
+ describe "#order_count" do
+ let(:order_ids) { [1, 2, 3, 4, 5, 6, 7] }
+ it "counts the number of items in the order_ids instance_variable" do
+ summary.instance_variable_set(:@order_ids, order_ids)
+ expect(summary.order_count).to be 7
+ end
+ end
+
+ describe "#success_count" do
+ let(:success_ids) { [1, 2, 3, 4, 5, 6, 7] }
+ it "counts the number of items in the success_ids instance_variable" do
+ summary.instance_variable_set(:@success_ids, success_ids)
+ expect(summary.success_count).to be 7
+ end
+ end
+
+ describe "#issue_count" do
+ let(:order_ids) { [1, 3, 5, 7, 9] }
+ let(:success_ids) { [1, 2, 3, 4, 5] }
+
+ it "counts the number of items in order_ids that are not in success_ids" do
+ summary.instance_variable_set(:@order_ids, order_ids)
+ summary.instance_variable_set(:@success_ids, success_ids)
+ expect(summary.issue_count).to be 2 # 7 & 9
+ end
+ end
+
+ describe "#orders_affected_by" do
+ let(:order1) { create(:order) }
+ let(:order2) { create(:order) }
+
+ before do
+ allow(summary).to receive(:unrecorded_ids) { [order1.id] }
+ allow(summary).to receive(:issues) { { failure: { order2.id => "A message" } } }
+ end
+
+ context "when the issue type is :other" do
+ let(:orders) { summary.orders_affected_by(:other) }
+
+ it "returns orders specified by unrecorded_ids" do
+ expect(orders).to include order1
+ expect(orders).to_not include order2
+ end
+ end
+
+ context "when the issue type is :other" do
+ let(:orders) { summary.orders_affected_by(:failure) }
+
+ it "returns orders specified by the relevant issue hash" do
+ expect(orders).to include order2
+ expect(orders).to_not include order1
+ end
+ end
+ end
+
+ describe "#unrecorded_ids" do
+ let(:issues) { { type: { 7 => "message", 8 => "message" } } }
+
+ before do
+ summary.instance_variable_set(:@order_ids, [1, 3, 5, 7, 9])
+ summary.instance_variable_set(:@success_ids, [1, 2, 3, 4, 5])
+ summary.instance_variable_set(:@issues, issues)
+ end
+
+ it "returns order_ids that are not marked as an issue or a success" do
+ expect(summary.unrecorded_ids).to eq [9]
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb
new file mode 100644
index 0000000000..7c52fba12a
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb
@@ -0,0 +1,524 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+module OrderManagement
+ module Subscriptions
+ describe Validator do
+ let(:owner) { create(:user) }
+ let(:shop) { create(:enterprise, name: "Shop", owner: owner) }
+
+ describe "delegation" do
+ let(:subscription) { create(:subscription, shop: shop) }
+ let(:validator) { Validator.new(subscription) }
+
+ it "delegates to subscription" do
+ expect(validator.shop).to eq subscription.shop
+ expect(validator.customer).to eq subscription.customer
+ expect(validator.schedule).to eq subscription.schedule
+ expect(validator.shipping_method).to eq subscription.shipping_method
+ expect(validator.payment_method).to eq subscription.payment_method
+ expect(validator.bill_address).to eq subscription.bill_address
+ expect(validator.ship_address).to eq subscription.ship_address
+ expect(validator.begins_at).to eq subscription.begins_at
+ expect(validator.ends_at).to eq subscription.ends_at
+ end
+ end
+
+ describe "validations" do
+ let(:subscription_stubs) do
+ {
+ shop: shop,
+ customer: true,
+ schedule: true,
+ shipping_method: true,
+ payment_method: true,
+ bill_address: true,
+ ship_address: true,
+ begins_at: true,
+ ends_at: true,
+ }
+ end
+
+ let(:validation_stubs) do
+ {
+ shipping_method_allowed?: true,
+ payment_method_allowed?: true,
+ payment_method_type_allowed?: true,
+ ends_at_after_begins_at?: true,
+ customer_allowed?: true,
+ schedule_allowed?: true,
+ credit_card_ok?: true,
+ subscription_line_items_present?: true,
+ requested_variants_available?: true
+ }
+ end
+
+ let(:subscription) { instance_double(Subscription, subscription_stubs) }
+ let(:validator) { OrderManagement::Subscriptions::Validator.new(subscription) }
+
+ def stub_validations(validator, methods)
+ methods.each do |name, value|
+ allow(validator).to receive(name) { value }
+ end
+ end
+
+ describe "shipping method validation" do
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:shipping_method))
+ }
+ before { stub_validations(validator, validation_stubs.except(:shipping_method_allowed?)) }
+
+ context "when no shipping method is present" do
+ before { expect(subscription).to receive(:shipping_method).at_least(:once) { nil } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:shipping_method]).to_not be_empty
+ end
+ end
+
+ context "when a shipping method is present" do
+ let(:shipping_method) { instance_double(Spree::ShippingMethod, distributors: [shop]) }
+ before {
+ expect(subscription).to receive(:shipping_method).at_least(:once) { shipping_method }
+ }
+
+ context "and the shipping method is not associated with the shop" do
+ before { allow(shipping_method).to receive(:distributors) { [double(:enterprise)] } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:shipping_method]).to_not be_empty
+ end
+ end
+
+ context "and the shipping method is associated with the shop" do
+ before { allow(shipping_method).to receive(:distributors) { [shop] } }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:shipping_method]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "payment method validation" do
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:payment_method))
+ }
+ before { stub_validations(validator, validation_stubs.except(:payment_method_allowed?)) }
+
+ context "when no payment method is present" do
+ before { expect(subscription).to receive(:payment_method).at_least(:once) { nil } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "when a payment method is present" do
+ let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) }
+ before {
+ expect(subscription).to receive(:payment_method).at_least(:once) { payment_method }
+ }
+
+ context "and the payment method is not associated with the shop" do
+ before { allow(payment_method).to receive(:distributors) { [double(:enterprise)] } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "and the payment method is associated with the shop" do
+ before { allow(payment_method).to receive(:distributors) { [shop] } }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:payment_method]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "payment method type validation" do
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:payment_method))
+ }
+ before {
+ stub_validations(validator, validation_stubs.except(:payment_method_type_allowed?))
+ }
+
+ context "when a payment method is present" do
+ let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) }
+ before {
+ expect(subscription).to receive(:payment_method).at_least(:once) { payment_method }
+ }
+
+ context "and the payment method type is not in the approved list" do
+ before { allow(payment_method).to receive(:type) { "Blah" } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "and the payment method is in the approved list" do
+ let(:approved_type) { Subscription::ALLOWED_PAYMENT_METHOD_TYPES.first }
+ before { allow(payment_method).to receive(:type) { approved_type } }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:payment_method]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "dates" do
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:begins_at, :ends_at))
+ }
+ before { stub_validations(validator, validation_stubs.except(:ends_at_after_begins_at?)) }
+ before { expect(subscription).to receive(:begins_at).at_least(:once) { begins_at } }
+
+ context "when no begins_at is present" do
+ let(:begins_at) { nil }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:begins_at]).to_not be_empty
+ end
+ end
+
+ context "when a start date is present" do
+ let(:begins_at) { Time.zone.today }
+ before { expect(subscription).to receive(:ends_at).at_least(:once) { ends_at } }
+
+ context "when no ends_at is present" do
+ let(:ends_at) { nil }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:ends_at]).to be_empty
+ end
+ end
+
+ context "when ends_at is equal to begins_at" do
+ let(:ends_at) { Time.zone.today }
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:ends_at]).to_not be_empty
+ end
+ end
+
+ context "when ends_at is before begins_at" do
+ let(:ends_at) { Time.zone.today - 1.day }
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:ends_at]).to_not be_empty
+ end
+ end
+
+ context "when ends_at is after begins_at" do
+ let(:ends_at) { Time.zone.today + 1.day }
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:ends_at]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "addresses" do
+ before { stub_validations(validator, validation_stubs) }
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:bill_address, :ship_address))
+ }
+ before { expect(subscription).to receive(:bill_address).at_least(:once) { bill_address } }
+ before { expect(subscription).to receive(:ship_address).at_least(:once) { ship_address } }
+
+ context "when bill_address and ship_address are not present" do
+ let(:bill_address) { nil }
+ let(:ship_address) { nil }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:bill_address]).to_not be_empty
+ expect(validator.errors[:ship_address]).to_not be_empty
+ end
+ end
+
+ context "when bill_address and ship_address are present" do
+ let(:bill_address) { instance_double(Spree::Address) }
+ let(:ship_address) { instance_double(Spree::Address) }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:bill_address]).to be_empty
+ expect(validator.errors[:ship_address]).to be_empty
+ end
+ end
+ end
+
+ describe "customer" do
+ let(:subscription) { instance_double(Subscription, subscription_stubs.except(:customer)) }
+ before { stub_validations(validator, validation_stubs.except(:customer_allowed?)) }
+ before { expect(subscription).to receive(:customer).at_least(:once) { customer } }
+
+ context "when no customer is present" do
+ let(:customer) { nil }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:customer]).to_not be_empty
+ end
+ end
+
+ context "when a customer is present" do
+ let(:customer) { instance_double(Customer) }
+
+ context "and the customer is not associated with the shop" do
+ before { allow(customer).to receive(:enterprise) { double(:enterprise) } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:customer]).to_not be_empty
+ end
+ end
+
+ context "and the customer is associated with the shop" do
+ before { allow(customer).to receive(:enterprise) { shop } }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:customer]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "schedule" do
+ let(:subscription) { instance_double(Subscription, subscription_stubs.except(:schedule)) }
+ before { stub_validations(validator, validation_stubs.except(:schedule_allowed?)) }
+ before { expect(subscription).to receive(:schedule).at_least(:once) { schedule } }
+
+ context "when no schedule is present" do
+ let(:schedule) { nil }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:schedule]).to_not be_empty
+ end
+ end
+
+ context "when a schedule is present" do
+ let(:schedule) { instance_double(Schedule) }
+
+ context "and the schedule is not associated with the shop" do
+ before { allow(schedule).to receive(:coordinators) { [double(:enterprise)] } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:schedule]).to_not be_empty
+ end
+ end
+
+ context "and the schedule is associated with the shop" do
+ before { allow(schedule).to receive(:coordinators) { [shop] } }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:schedule]).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "credit card" do
+ let(:subscription) {
+ instance_double(Subscription, subscription_stubs.except(:payment_method))
+ }
+ before { stub_validations(validator, validation_stubs.except(:credit_card_ok?)) }
+ before {
+ expect(subscription).to receive(:payment_method).at_least(:once) { payment_method }
+ }
+
+ context "when using a Check payment method" do
+ let(:payment_method) {
+ instance_double(Spree::PaymentMethod, type: "Spree::PaymentMethod::Check")
+ }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:subscription_line_items]).to be_empty
+ end
+ end
+
+ context "when using the StripeConnect payment gateway" do
+ let(:payment_method) {
+ instance_double(Spree::PaymentMethod, type: "Spree::Gateway::StripeConnect")
+ }
+ before { expect(subscription).to receive(:customer).at_least(:once) { customer } }
+
+ context "when the customer does not allow charges" do
+ let(:customer) { instance_double(Customer, allow_charges: false) }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "when the customer allows charges" do
+ let(:customer) { instance_double(Customer, allow_charges: true) }
+
+ context "and the customer is not associated with a user" do
+ before { allow(customer).to receive(:user) { nil } }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "and the customer is associated with a user" do
+ before { expect(customer).to receive(:user).once { user } }
+
+ context "and the user has no default card set" do
+ let(:user) { instance_double(Spree::User, default_card: nil) }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:payment_method]).to_not be_empty
+ end
+ end
+
+ context "and the user has a default card set" do
+ let(:user) { instance_double(Spree::User, default_card: 'some card') }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:payment_method]).to be_empty
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe "subscription line items" do
+ let(:subscription) { instance_double(Subscription, subscription_stubs) }
+ before {
+ stub_validations(validator, validation_stubs.except(:subscription_line_items_present?))
+ }
+ before {
+ expect(subscription).to receive(:subscription_line_items).at_least(:once) {
+ subscription_line_items
+ }
+ }
+
+ context "when no subscription line items exist" do
+ let(:subscription_line_items) { [] }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:subscription_line_items]).to_not be_empty
+ end
+ end
+
+ context "when subscription line items exist but all are marked for destruction" do
+ let(:subscription_line_item1) {
+ instance_double(SubscriptionLineItem, marked_for_destruction?: true)
+ }
+ let(:subscription_line_items) { [subscription_line_item1] }
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:subscription_line_items]).to_not be_empty
+ end
+ end
+
+ context "when subscription line items exist and some are not marked for destruction" do
+ let(:subscription_line_item1) {
+ instance_double(SubscriptionLineItem, marked_for_destruction?: true)
+ }
+ let(:subscription_line_item2) {
+ instance_double(SubscriptionLineItem, marked_for_destruction?: false)
+ }
+ let(:subscription_line_items) { [subscription_line_item1, subscription_line_item2] }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:subscription_line_items]).to be_empty
+ end
+ end
+ end
+
+ describe "variant availability" do
+ let(:subscription) { instance_double(Subscription, subscription_stubs) }
+ before {
+ stub_validations(validator, validation_stubs.except(:requested_variants_available?))
+ }
+ before {
+ expect(subscription).to receive(:subscription_line_items).at_least(:once) {
+ subscription_line_items
+ }
+ }
+
+ context "when no subscription line items exist" do
+ let(:subscription_line_items) { [] }
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:subscription_line_items]).to be_empty
+ end
+ end
+
+ context "when subscription line items exist" do
+ let(:variant1) { instance_double(Spree::Variant, id: 1) }
+ let(:variant2) { instance_double(Spree::Variant, id: 2) }
+ let(:subscription_line_item1) {
+ instance_double(SubscriptionLineItem, variant: variant1)
+ }
+ let(:subscription_line_item2) {
+ instance_double(SubscriptionLineItem, variant: variant2)
+ }
+ let(:subscription_line_items) { [subscription_line_item1] }
+
+ context "but some variants are unavailable" do
+ let(:product) { instance_double(Spree::Product, name: "some_name") }
+
+ before do
+ allow(validator).to receive(:available_variant_ids) { [variant2.id] }
+ allow(variant1).to receive(:product) { product }
+ allow(variant1).to receive(:full_name) { "some name" }
+ end
+
+ it "adds an error and returns false" do
+ expect(validator.valid?).to be false
+ expect(validator.errors[:subscription_line_items]).to_not be_empty
+ end
+ end
+
+ context "and all requested variants are available" do
+ before do
+ allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] }
+ end
+
+ it "returns true" do
+ expect(validator.valid?).to be true
+ expect(validator.errors[:subscription_line_items]).to be_empty
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb
new file mode 100644
index 0000000000..2ea3206045
--- /dev/null
+++ b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+module OrderManagement
+ module Subscriptions
+ describe VariantsList do
+ describe "variant eligibility for subscription" do
+ let!(:shop) { create(:distributor_enterprise) }
+ let!(:producer) { create(:supplier_enterprise) }
+ let!(:product) { create(:product, supplier: producer) }
+ let!(:variant) { product.variants.first }
+
+ let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
+ let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) }
+ let!(:subscription_line_item) do
+ create(:subscription_line_item, subscription: subscription, variant: variant)
+ end
+
+ let(:current_order_cycle) do
+ create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago,
+ orders_close_at: 1.week.from_now)
+ end
+
+ let(:future_order_cycle) do
+ create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now,
+ orders_close_at: 2.weeks.from_now)
+ end
+
+ let(:past_order_cycle) do
+ create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago,
+ orders_close_at: 1.week.ago)
+ end
+
+ let!(:order_cycle) { current_order_cycle }
+
+ context "if the shop is the supplier for the product" do
+ let!(:producer) { shop }
+
+ it "is eligible" do
+ expect(described_class.eligible_variants(shop)).to include(variant)
+ end
+ end
+
+ context "if the supplier is permitted for the shop" do
+ let!(:enterprise_relationship) {
+ create(:enterprise_relationship, child: shop,
+ parent: product.supplier,
+ permissions_list: [:add_to_order_cycle])
+ }
+
+ it "is eligible" do
+ expect(described_class.eligible_variants(shop)).to include(variant)
+ end
+ end
+
+ context "if the variant is involved in an exchange" do
+ let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
+ let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
+
+ context "if it is an incoming exchange where the shop is the receiver" do
+ let!(:incoming_exchange) {
+ order_cycle.exchanges.create(sender: product.supplier,
+ receiver: shop,
+ incoming: true, variants: [variant])
+ }
+
+ it "is not eligible" do
+ expect(described_class.eligible_variants(shop)).to_not include(variant)
+ end
+ end
+
+ context "if it is an outgoing exchange where the shop is the receiver" do
+ let!(:outgoing_exchange) {
+ order_cycle.exchanges.create(sender: product.supplier,
+ receiver: shop,
+ incoming: false,
+ variants: [variant])
+ }
+
+ context "if the order cycle is currently open" do
+ let!(:order_cycle) { current_order_cycle }
+
+ it "is eligible" do
+ expect(described_class.eligible_variants(shop)).to include(variant)
+ end
+ end
+
+ context "if the order cycle opens in the future" do
+ let!(:order_cycle) { future_order_cycle }
+
+ it "is eligible" do
+ expect(described_class.eligible_variants(shop)).to include(variant)
+ end
+ end
+
+ context "if the order cycle closed in the past" do
+ let!(:order_cycle) { past_order_cycle }
+
+ it "is eligible" do
+ expect(described_class.eligible_variants(shop)).to include(variant)
+ end
+ end
+ end
+ end
+
+ context "if the variant is unrelated" do
+ it "is not eligible" do
+ expect(described_class.eligible_variants(shop)).to_not include(variant)
+ end
+ end
+ end
+
+ describe "checking if variant in open and upcoming order cycles" do
+ let!(:shop) { create(:enterprise) }
+ let!(:product) { create(:product) }
+ let!(:variant) { product.variants.first }
+ let!(:schedule) { create(:schedule) }
+
+ context "if the variant is involved in an exchange" do
+ let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
+ let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
+
+ context "if it is an incoming exchange where the shop is the receiver" do
+ let!(:incoming_exchange) {
+ order_cycle.exchanges.create(sender: product.supplier,
+ receiver: shop,
+ incoming: true,
+ variants: [variant])
+ }
+
+ it "is is false" do
+ expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop,
+ schedule,
+ variant)
+ end
+ end
+
+ context "if it is an outgoing exchange where the shop is the receiver" do
+ let!(:outgoing_exchange) {
+ order_cycle.exchanges.create(sender: product.supplier,
+ receiver: shop,
+ incoming: false,
+ variants: [variant])
+ }
+
+ it "is true" do
+ expect(described_class).to be_in_open_and_upcoming_order_cycles(shop,
+ schedule,
+ variant)
+ end
+ end
+ end
+
+ context "if the variant is unrelated" do
+ it "is false" do
+ expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop,
+ schedule,
+ variant)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/engines/web/config/routes.rb b/engines/web/config/routes.rb
index 121f3bdd9a..0b56f00a6d 100644
--- a/engines/web/config/routes.rb
+++ b/engines/web/config/routes.rb
@@ -1,9 +1,7 @@
-Web::Engine.routes.draw do
- namespace :api do
- scope '/cookies' do
- resource :consent, only: [:show, :create, :destroy], controller: "cookies_consent"
- end
+Openfoodnetwork::Application.routes.prepend do
+ scope '/api/cookies' do
+ resource :consent, only: [:show, :create, :destroy], controller: "web/api/cookies_consent"
end
- get "/angular-templates/:id", to: "angular_templates#show", constraints: { name: %r{[\/\w\.]+} }
+ get "/angular-templates/:id", to: "web/angular_templates#show", constraints: { name: %r{[\/\w\.]+} }
end
diff --git a/spec/features/consumer/cookies_spec.rb b/engines/web/spec/features/consumer/cookies_spec.rb
similarity index 100%
rename from spec/features/consumer/cookies_spec.rb
rename to engines/web/spec/features/consumer/cookies_spec.rb
diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb
index 90b0ff59c9..f386be439a 100644
--- a/lib/open_food_network/orders_and_fulfillments_report.rb
+++ b/lib/open_food_network/orders_and_fulfillments_report.rb
@@ -18,6 +18,7 @@ module OpenFoodNetwork
@options = options
@report_type = options[:report_type]
@render_table = render_table
+ @variant_scopers_by_distributor_id = {}
end
def search
@@ -56,6 +57,14 @@ module OpenFoodNetwork
total_units.round(3)
end
+ def variant_scoper_for(distributor_id)
+ @variant_scopers_by_distributor_id[distributor_id] ||=
+ OpenFoodNetwork::ScopeVariantToHub.new(
+ distributor_id,
+ report_variant_overrides[distributor_id] || {},
+ )
+ end
+
private
def report
@@ -89,5 +98,13 @@ module OpenFoodNetwork
def report_line_items
@report_line_items ||= Reports::LineItems.new(order_permissions, options)
end
+
+ def report_variant_overrides
+ @report_variant_overrides ||=
+ VariantOverridesIndexed.new(
+ order_permissions.visible_line_items.select('DISTINCT variant_id'),
+ report_line_items.orders.result.select('DISTINCT distributor_id'),
+ ).indexed
+ end
end
end
diff --git a/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb
index 593933e157..8225d45eea 100644
--- a/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb
+++ b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb
@@ -7,9 +7,11 @@ module OpenFoodNetwork
attr_reader :context
delegate :line_item_name, to: :context
+ delegate :variant_scoper_for, to: :context
def initialize(context)
@context = context
+ @scopers_by_distributor_id = {}
end
# rubocop:disable Metrics/AbcSize
@@ -159,7 +161,11 @@ module OpenFoodNetwork
},
proc { |_line_items| "" },
- proc { |line_items| line_items.first.variant.sku },
+ proc do |line_items|
+ line_item = line_items.first
+ variant_scoper_for(line_item.order.distributor_id).scope(line_item.variant)
+ line_item.variant.sku
+ end,
proc { |line_items| line_items.first.order.order_cycle.andand.name },
proc { |line_items|
diff --git a/lib/open_food_network/proxy_order_syncer.rb b/lib/open_food_network/proxy_order_syncer.rb
deleted file mode 100644
index 8f867057ab..0000000000
--- a/lib/open_food_network/proxy_order_syncer.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-module OpenFoodNetwork
- class ProxyOrderSyncer
- attr_reader :subscription
-
- delegate :order_cycles, :proxy_orders, :begins_at, :ends_at, to: :subscription
-
- def initialize(subscriptions)
- case subscriptions
- when Subscription
- @subscription = subscriptions
- when ActiveRecord::Relation
- @subscriptions = subscriptions.not_ended.not_canceled
- else
- raise "ProxyOrderSyncer must be initialized with " \
- "an instance of Subscription or ActiveRecord::Relation"
- end
- end
-
- def sync!
- return sync_subscriptions! if @subscriptions
-
- return initialise_proxy_orders! unless @subscription.id
-
- sync_subscription!
- end
-
- private
-
- def sync_subscriptions!
- @subscriptions.each do |subscription|
- @subscription = subscription
- sync_subscription!
- end
- end
-
- def initialise_proxy_orders!
- uninitialised_order_cycle_ids.each do |order_cycle_id|
- Rails.logger.info "Initializing Proxy Order " \
- "of subscription #{@subscription.id} in order cycle #{order_cycle_id}"
- proxy_orders << ProxyOrder.new(subscription: subscription, order_cycle_id: order_cycle_id)
- end
- end
-
- def sync_subscription!
- Rails.logger.info "Syncing Proxy Orders of subscription #{@subscription.id}"
- create_proxy_orders!
- remove_orphaned_proxy_orders!
- end
-
- def create_proxy_orders!
- return unless not_closed_in_range_order_cycles.any?
-
- query = "INSERT INTO proxy_orders (subscription_id, order_cycle_id, updated_at, created_at)"
- query << " VALUES #{insert_values}"
- query << " ON CONFLICT DO NOTHING"
-
- ActiveRecord::Base.connection.exec_query(query)
- end
-
- def uninitialised_order_cycle_ids
- not_closed_in_range_order_cycles.pluck(:id) - proxy_orders.map(&:order_cycle_id)
- end
-
- def remove_orphaned_proxy_orders!
- orphaned_proxy_orders.where(nil).delete_all
- end
-
- # Remove Proxy Orders that have not been placed yet
- # and are in Order Cycles that are out of range
- def orphaned_proxy_orders
- orphaned = proxy_orders.where(placed_at: nil)
- order_cycle_ids = in_range_order_cycles.pluck(:id)
- return orphaned unless order_cycle_ids.any?
-
- orphaned.where('order_cycle_id NOT IN (?)', order_cycle_ids)
- end
-
- def insert_values
- now = Time.now.utc.iso8601
- not_closed_in_range_order_cycles
- .map{ |oc| "(#{subscription.id},#{oc.id},'#{now}','#{now}')" }
- .join(",")
- end
-
- def not_closed_in_range_order_cycles
- in_range_order_cycles.merge(OrderCycle.not_closed)
- end
-
- def in_range_order_cycles
- order_cycles.where("orders_close_at >= ? AND orders_close_at <= ?",
- begins_at,
- ends_at || 100.years.from_now)
- end
- end
-end
diff --git a/lib/open_food_network/scope_variants_for_search.rb b/lib/open_food_network/scope_variants_for_search.rb
index ddf1d48771..5d16eafefe 100644
--- a/lib/open_food_network/scope_variants_for_search.rb
+++ b/lib/open_food_network/scope_variants_for_search.rb
@@ -61,7 +61,7 @@ module OpenFoodNetwork
end
def scope_to_eligible_for_subscriptions_in_distributor
- eligible_variants_scope = SubscriptionVariantsService.eligible_variants(distributor)
+ eligible_variants_scope = OrderManagement::Subscriptions::VariantsList.eligible_variants(distributor)
@variants = @variants.merge(eligible_variants_scope)
scope_variants_to_distributor(@variants, distributor)
end
diff --git a/lib/open_food_network/subscription_payment_updater.rb b/lib/open_food_network/subscription_payment_updater.rb
deleted file mode 100644
index 4a9c8fa144..0000000000
--- a/lib/open_food_network/subscription_payment_updater.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-module OpenFoodNetwork
- class SubscriptionPaymentUpdater
- def initialize(order)
- @order = order
- end
-
- def update!
- create_payment
- ensure_payment_source
- return if order.errors.any?
-
- payment.update_attributes(amount: order.outstanding_balance)
- end
-
- private
-
- attr_reader :order
-
- def payment
- @payment ||= order.pending_payments.last
- end
-
- def create_payment
- return if payment.present?
-
- @payment = order.payments.create(
- payment_method_id: order.subscription.payment_method_id,
- amount: order.outstanding_balance
- )
- end
-
- def card_required?
- [Spree::Gateway::StripeConnect,
- Spree::Gateway::StripeSCA].include? payment.payment_method.class
- end
-
- def card_set?
- payment.source is_a? Spree::CreditCard
- end
-
- def ensure_payment_source
- return unless card_required? && !card_set?
-
- ensure_credit_card || order.errors.add(:base, :no_card)
- end
-
- def ensure_credit_card
- return false if saved_credit_card.blank? || !allow_charges?
-
- payment.update_attributes(source: saved_credit_card)
- end
-
- def allow_charges?
- order.customer.allow_charges?
- end
-
- def saved_credit_card
- order.user.default_card
- end
-
- def errors_present?
- order.errors.any?
- end
- end
-end
diff --git a/lib/open_food_network/subscription_summarizer.rb b/lib/open_food_network/subscription_summarizer.rb
deleted file mode 100644
index 6e4b95da8b..0000000000
--- a/lib/open_food_network/subscription_summarizer.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'open_food_network/subscription_summary'
-
-# Used by for SubscriptionPlacementJob and SubscriptionConfirmJob to summarize the
-# result of automatic processing of subscriptions for the relevant shop owners.
-module OpenFoodNetwork
- class SubscriptionSummarizer
- def initialize
- @summaries = {}
- end
-
- def record_order(order)
- summary_for(order).record_order(order)
- end
-
- def record_success(order)
- summary_for(order).record_success(order)
- end
-
- def record_issue(type, order, message = nil)
- Rails.logger.info "Issue in Subscription Order #{order.id}: #{type}"
- summary_for(order).record_issue(type, order, message)
- end
-
- def record_and_log_error(type, order)
- return record_issue(type, order) unless order.errors.any?
-
- error = "Subscription#{type.to_s.camelize}Error"
- line1 = "#{error}: Cannot process order #{order.number} due to errors"
- line2 = "Errors: #{order.errors.full_messages.join(', ')}"
- Rails.logger.info("#{line1}\n#{line2}")
- record_issue(type, order, line2)
- end
-
- def send_placement_summary_emails
- @summaries.values.each do |summary|
- SubscriptionMailer.placement_summary_email(summary).deliver
- end
- end
-
- def send_confirmation_summary_emails
- @summaries.values.each do |summary|
- SubscriptionMailer.confirmation_summary_email(summary).deliver
- end
- end
-
- private
-
- def summary_for(order)
- shop_id = order.distributor_id
- @summaries[shop_id] ||= SubscriptionSummary.new(shop_id)
- end
- end
-end
diff --git a/lib/open_food_network/subscription_summary.rb b/lib/open_food_network/subscription_summary.rb
deleted file mode 100644
index fb2a1dc066..0000000000
--- a/lib/open_food_network/subscription_summary.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-module OpenFoodNetwork
- class SubscriptionSummary
- attr_reader :shop_id, :order_count, :success_count, :issues
-
- def initialize(shop_id)
- @shop_id = shop_id
- @order_ids = []
- @success_ids = []
- @issues = {}
- end
-
- def record_order(order)
- @order_ids << order.id
- end
-
- def record_success(order)
- @success_ids << order.id
- end
-
- def record_issue(type, order, message)
- issues[type] ||= {}
- issues[type][order.id] = message
- end
-
- def order_count
- @order_ids.count
- end
-
- def success_count
- @success_ids.count
- end
-
- def issue_count
- (@order_ids - @success_ids).count
- end
-
- def orders_affected_by(type)
- case type
- when :other then Spree::Order.where(id: unrecorded_ids)
- else Spree::Order.where(id: issues[type].keys)
- end
- end
-
- def unrecorded_ids
- recorded_ids = issues.values.map(&:keys).flatten
- @order_ids - @success_ids - recorded_ids
- end
- end
-end
diff --git a/lib/tasks/sample_data/group_factory.rb b/lib/tasks/sample_data/group_factory.rb
index 15e1ed1fb9..1e63866582 100644
--- a/lib/tasks/sample_data/group_factory.rb
+++ b/lib/tasks/sample_data/group_factory.rb
@@ -10,19 +10,21 @@ class GroupFactory
return if EnterpriseGroup.where(name: "Producer group").exists?
create_group(
- name: "Producer group",
- owner: enterprises.first.owner,
- on_front_page: true,
- description: "The seed producers",
- address: "6 Rollings Road, Upper Ferntree Gully, 3156"
+ {
+ name: "Producer group",
+ owner: enterprises.first.owner,
+ on_front_page: true,
+ description: "The seed producers"
+ },
+ "6 Rollings Road, Upper Ferntree Gully, 3156"
)
end
private
- def create_group(params)
+ def create_group(params, group_address)
group = EnterpriseGroup.new(params)
- group.address = address(params[:address])
+ group.address = address(group_address)
group.enterprises = enterprises
group.save!
end
diff --git a/lib/templates/erb/scaffold/_form.html.erb b/lib/templates/erb/scaffold/_form.html.erb
deleted file mode 100644
index 201a069e2c..0000000000
--- a/lib/templates/erb/scaffold/_form.html.erb
+++ /dev/null
@@ -1,13 +0,0 @@
-<%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
- <%%= f.error_notification %>
-
-
- <%- attributes.each do |attribute| -%>
- <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
- <%- end -%>
-
-
-
- <%%= f.button :submit %>
-
-<%% end %>
diff --git a/script/mirror_db.sh b/script/mirror_db.sh
index ede932c821..c69db3490d 100755
--- a/script/mirror_db.sh
+++ b/script/mirror_db.sh
@@ -10,6 +10,7 @@ HOST="$1"
BUCKET="$2"
: ${DB_USER='ofn_user'}
: ${DB_DATABASE='openfoodnetwork'}
+: ${DB_CACHE_FILE="tmp/$HOST.sql"}
DB_OPTIONS=(
--exclude-table-data=sessions
@@ -32,20 +33,30 @@ fi
# -- Mirror database
echo "Mirroring database..."
-dropdb -h localhost -U ofn open_food_network_dev
+dropdb -h localhost -U ofn open_food_network_dev --if-exists
createdb -h localhost -U ofn open_food_network_dev
-ssh -C "$HOST" "pg_dump -h localhost -U $DB_USER $DB_DATABASE ${DB_OPTIONS[@]}" | psql -h localhost -U ofn open_food_network_dev
+
+if [ -s "$DB_CACHE_FILE" ]; then
+ echo "Using cached dump '$DB_CACHE_FILE'."
+ psql -h localhost -U ofn open_food_network_dev < "$DB_CACHE_FILE"
+else
+ echo "Downlowding dump to '$DB_CACHE_FILE'."
+ ssh -C "$HOST" "pg_dump -h localhost -U $DB_USER $DB_DATABASE ${DB_OPTIONS[@]}"\
+ | tee "$DB_CACHE_FILE"\
+ | psql -h localhost -U ofn open_food_network_dev
+fi
# -- Disable S3
echo "Preparing mirrored database..."
$RAILS_RUN script/prepare_imported_db.rb
# -- Mirror images
-if [ -n "$BUCKET" ] && hash aws 2>/dev/null; then
+if [ -n "$BUCKET" ]; then
+ if hash aws 2>/dev/null; then
echo "Mirroring images..."
aws s3 sync "s3://$BUCKET/public public/"
-
-else
+ else
echo "Please install the AWS CLI tools so that I can copy the images from $BUCKET for you."
echo "eg. sudo easy_install awscli"
+ fi
fi
diff --git a/spec/controllers/admin/schedules_controller_spec.rb b/spec/controllers/admin/schedules_controller_spec.rb
index 299ff5e4d2..99b73f4e03 100644
--- a/spec/controllers/admin/schedules_controller_spec.rb
+++ b/spec/controllers/admin/schedules_controller_spec.rb
@@ -90,7 +90,7 @@ describe Admin::SchedulesController, type: :controller do
it "syncs proxy orders when order_cycle_ids change" do
syncer_mock = double(:syncer)
- allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock }
+ allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock }
expect(syncer_mock).to receive(:sync!).exactly(2).times
spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: [coordinated_order_cycle.id, coordinated_order_cycle2.id]
@@ -150,7 +150,7 @@ describe Admin::SchedulesController, type: :controller do
it "sync proxy orders" do
syncer_mock = double(:syncer)
- allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock }
+ allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock }
expect(syncer_mock).to receive(:sync!).once
create_schedule params
diff --git a/spec/controllers/api/enterprises_controller_spec.rb b/spec/controllers/api/enterprises_controller_spec.rb
index 15c4606567..ef21340e3f 100644
--- a/spec/controllers/api/enterprises_controller_spec.rb
+++ b/spec/controllers/api/enterprises_controller_spec.rb
@@ -92,29 +92,5 @@ module Api
end
end
end
-
- context "as a non-authenticated user" do
- let!(:hub) {
- create(:distributor_enterprise, with_payment_and_shipping: true, name: 'Shopfront Test Hub')
- }
- let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') }
- let!(:category) { create(:taxon, name: 'Fruit') }
- let!(:product) { create(:product, supplier: producer, primary_taxon: category ) }
- let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) }
-
- before do
- allow(controller).to receive(:spree_current_user) { nil }
- end
-
- describe "fetching shopfronts data" do
- it "returns data for an enterprise" do
- spree_get :shopfront, id: producer.id, format: :json
-
- expect(json_response['name']).to eq 'Shopfront Test Producer'
- expect(json_response['hubs'][0]['name']).to eq 'Shopfront Test Hub'
- expect(json_response['supplied_taxons'][0]['name']).to eq 'Fruit'
- end
- end
- end
end
end
diff --git a/spec/controllers/api/shops_controller_spec.rb b/spec/controllers/api/shops_controller_spec.rb
new file mode 100644
index 0000000000..3ae4e55a01
--- /dev/null
+++ b/spec/controllers/api/shops_controller_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+module Api
+ describe ShopsController, type: :controller do
+ include AuthenticationWorkflow
+ render_views
+
+ context "as a non-authenticated user" do
+ let!(:hub) {
+ create(:distributor_enterprise, with_payment_and_shipping: true, name: 'Shopfront Test Hub')
+ }
+ let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') }
+ let!(:category) { create(:taxon, name: 'Fruit') }
+ let!(:product) { create(:product, supplier: producer, primary_taxon: category ) }
+ let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) }
+ let!(:closed_hub1) { create(:distributor_enterprise) }
+ let!(:closed_hub2) { create(:distributor_enterprise) }
+
+ before do
+ allow(controller).to receive(:spree_current_user) { nil }
+ end
+
+ describe "#show" do
+ it "returns shopfront data for an enterprise" do
+ spree_get :show, id: producer.id
+
+ expect(json_response['name']).to eq 'Shopfront Test Producer'
+ expect(json_response['hubs'][0]['name']).to eq 'Shopfront Test Hub'
+ expect(json_response['supplied_taxons'][0]['name']).to eq 'Fruit'
+ end
+ end
+
+ describe "#closed_shops" do
+ it "returns data for all closed shops" do
+ spree_get :closed_shops, nil
+
+ expect(json_response).not_to match hub.name
+ expect(json_response[0]['id']).to eq closed_hub1.id
+ expect(json_response[1]['id']).to eq closed_hub2.id
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/shops_controller_spec.rb b/spec/controllers/shops_controller_spec.rb
index 023e7b0245..9d468b7995 100644
--- a/spec/controllers/shops_controller_spec.rb
+++ b/spec/controllers/shops_controller_spec.rb
@@ -4,11 +4,7 @@ describe ShopsController, type: :controller do
include WebHelper
render_views
- let!(:distributor) { create(:distributor_enterprise) }
-
- before do
- allow(OpenFoodNetwork::EnterpriseInjectionData).to receive(:active_distributor_ids) { [distributor.id] }
- end
+ let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
it 'renders distributed product properties' do
product_property = create(:property, presentation: 'eggs')
diff --git a/spec/controllers/spree/admin/payments_controller_spec.rb b/spec/controllers/spree/admin/payments_controller_spec.rb
index 55b20d3484..53dd604ebd 100644
--- a/spec/controllers/spree/admin/payments_controller_spec.rb
+++ b/spec/controllers/spree/admin/payments_controller_spec.rb
@@ -12,16 +12,114 @@ describe Spree::Admin::PaymentsController, type: :controller do
context "#create" do
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
- let!(:order) do
- create(:order_with_totals_and_distribution, distributor: shop, state: "payment")
- end
-
let(:params) { { amount: order.total, payment_method_id: payment_method.id } }
- it "advances the order state" do
- expect {
- spree_post :create, payment: params, order_id: order.number
- }.to change { order.reload.state }.from("payment").to("complete")
+ context "order is not complete" do
+ let!(:order) do
+ create(:order_with_totals_and_distribution, distributor: shop, state: "payment")
+ end
+
+ it "advances the order state" do
+ expect {
+ spree_post :create, payment: params, order_id: order.number
+ }.to change { order.reload.state }.from("payment").to("complete")
+ end
+ end
+
+ context "order is complete" do
+ let!(:order) do
+ create(:order_with_totals_and_distribution, distributor: shop,
+ state: "complete",
+ completed_at: Time.zone.now)
+ end
+
+ context "with Check payment (payment.process! does nothing)" do
+ it "redirects to list of payments with success flash" do
+ spree_post :create, payment: params, order_id: order.number
+
+ redirects_to_list_of_payments_with_success_flash
+ expect(order.reload.payments.last.state).to eq "checkout"
+ end
+ end
+
+ context "with Stripe payment where payment.process! errors out" do
+ let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) }
+ before do
+ allow_any_instance_of(Spree::Payment).
+ to receive(:process!).
+ and_raise(Spree::Core::GatewayError.new("Payment Gateway Error"))
+ end
+
+ it "redirects to new payment page with flash error" do
+ spree_post :create, payment: params, order_id: order.number
+
+ redirects_to_new_payment_page_with_flash_error("Payment Gateway Error")
+ expect(order.reload.payments.last.state).to eq "checkout"
+ end
+ end
+
+ context "with StripeSCA payment" do
+ let!(:payment_method) { create(:stripe_sca_payment_method, distributors: [shop]) }
+
+ context "where payment.authorize! raises GatewayError" do
+ before do
+ allow_any_instance_of(Spree::Payment).
+ to receive(:authorize!).
+ and_raise(Spree::Core::GatewayError.new("Stripe Authorization Failure"))
+ end
+
+ it "redirects to new payment page with flash error" do
+ spree_post :create, payment: params, order_id: order.number
+
+ redirects_to_new_payment_page_with_flash_error("Stripe Authorization Failure")
+ expect(order.reload.payments.last.state).to eq "checkout"
+ end
+ end
+
+ context "where payment.authorize! does not move payment to pending state" do
+ before do
+ allow_any_instance_of(Spree::Payment).to receive(:authorize!).and_return(true)
+ end
+
+ it "redirects to new payment page with flash error" do
+ spree_post :create, payment: params, order_id: order.number
+
+ redirects_to_new_payment_page_with_flash_error("Authorization Failure")
+ expect(order.reload.payments.last.state).to eq "checkout"
+ end
+ end
+
+ context "where both payment.process! and payment.authorize! work" do
+ before do
+ allow_any_instance_of(Spree::Payment).to receive(:authorize!) do |payment|
+ payment.update_attribute :state, "pending"
+ end
+ allow_any_instance_of(Spree::Payment).to receive(:process!).and_return(true)
+ end
+
+ it "redirects to list of payments with success flash" do
+ spree_post :create, payment: params, order_id: order.number
+
+ redirects_to_list_of_payments_with_success_flash
+ expect(order.reload.payments.last.state).to eq "pending"
+ end
+ end
+ end
+
+ def redirects_to_list_of_payments_with_success_flash
+ expect_redirect_to spree.admin_order_payments_url(order)
+ expect(flash[:success]).to eq "Payment has been successfully created!"
+ end
+
+ def redirects_to_new_payment_page_with_flash_error(flash_error)
+ expect_redirect_to spree.new_admin_order_payment_url(order)
+ expect(flash[:error]).to eq flash_error
+ end
+
+ def expect_redirect_to(path)
+ expect(response.status).to eq 302
+ expect(response.location).to eq path
+ end
end
end
@@ -38,8 +136,10 @@ describe Spree::Admin::PaymentsController, type: :controller do
context "that was processed by stripe" do
let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) }
- # let!(:credit_card) { create(:credit_card, gateway_customer_profile_id: "cus_1", gateway_payment_profile_id: 'card_2') }
- let!(:payment) { create(:payment, order: order, state: 'completed', payment_method: payment_method, response_code: 'ch_1a2b3c', amount: order.total) }
+ let!(:payment) do
+ create(:payment, order: order, state: 'completed', payment_method: payment_method,
+ response_code: 'ch_1a2b3c', amount: order.total)
+ end
before do
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
@@ -49,7 +149,8 @@ describe Spree::Admin::PaymentsController, type: :controller do
before do
stub_request(:post, "https://api.stripe.com/v1/charges/ch_1a2b3c/refunds").
with(basic_auth: ["sk_test_12345", ""]).
- to_return(status: 200, body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') )
+ to_return(status: 200,
+ body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') )
end
it "voids the payment" do
@@ -94,7 +195,10 @@ describe Spree::Admin::PaymentsController, type: :controller do
context "that was processed by stripe" do
let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) }
- let!(:payment) { create(:payment, order: order, state: 'completed', payment_method: payment_method, response_code: 'ch_1a2b3c', amount: order.total + 5) }
+ let!(:payment) do
+ create(:payment, order: order, state: 'completed', payment_method: payment_method,
+ response_code: 'ch_1a2b3c', amount: order.total + 5)
+ end
before do
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
@@ -104,7 +208,8 @@ describe Spree::Admin::PaymentsController, type: :controller do
before do
stub_request(:post, "https://api.stripe.com/v1/charges/ch_1a2b3c/refunds").
with(basic_auth: ["sk_test_12345", ""]).
- to_return(status: 200, body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') )
+ to_return(status: 200,
+ body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') )
end
it "partially refunds the payment" do
diff --git a/spec/features/admin/order_print_ticket_spec.rb b/spec/features/admin/order_print_ticket_spec.rb
new file mode 100644
index 0000000000..add2ef9e7d
--- /dev/null
+++ b/spec/features/admin/order_print_ticket_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+feature '
+ As an administrator
+ I want to print a ticket for an order
+', js: true do
+ include AuthenticationWorkflow
+ include CheckoutHelper
+ include ActionView::Helpers::NumberHelper
+
+ context "as an enterprise manager" do
+ let!(:shipping_method) { create(:shipping_method, distributors: [distributor]) }
+ let!(:distributor) { create(:distributor_enterprise) }
+
+ let!(:order) do
+ create(:order_with_taxes, distributor: distributor, ship_address: create(:address),
+ product_price: 110, tax_rate_amount: 0.1,
+ tax_rate_name: "Tax 1").tap do |record|
+ Spree::TaxRate.adjust(record)
+ record.update_shipping_fees!
+ end
+ end
+
+ before do
+ @enterprise_user = create_enterprise_user
+ @enterprise_user.enterprise_roles.build(enterprise: distributor).save
+
+ quick_login_as @enterprise_user
+
+ Spree::Config[:enable_receipt_printing?] = true
+ end
+
+ feature "viewing the edit page" do
+ scenario "can print an order's ticket" do
+ visit spree.edit_admin_order_path(order)
+
+ find("#links-dropdown .ofn-drop-down").click
+
+ ticket_window = window_opened_by do
+ within('#links-dropdown') do
+ click_link('Print Ticket')
+ end
+ end
+
+ within_window ticket_window do
+ accept_alert do
+ print_data = page.evaluate_script('printData');
+ elements_in_print_data = [
+ order.distributor.name,
+ order.distributor.address.address_part1,
+ order.distributor.address.address_part2,
+ order.distributor.contact.email, order.number,
+ line_items_in_print_data,
+ adjustments_in_print_data,
+ order.display_total.format(with_currency: false),
+ taxes_in_print_data,
+ display_checkout_total_less_tax(order).format(with_currency: false)
+ ]
+ expect(print_data.join).to include(*elements_in_print_data.flatten)
+ end
+ end
+ end
+
+ def line_items_in_print_data
+ order.line_items.map { |line_item|
+ [line_item.quantity.to_s,
+ line_item.product.name,
+ line_item.single_display_amount_with_adjustments.format(symbol: false,
+ with_currency: false),
+ line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)]
+ }
+ end
+
+ def adjustments_in_print_data
+ checkout_adjustments_for(order, exclude: [:line_item]).
+ reject { |a| a.amount == 0 }.
+ map do |adjustment|
+ [raw(adjustment.label),
+ display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)]
+ end
+ end
+
+ def taxes_in_print_data
+ display_checkout_taxes_hash(order).map { |tax_rate, tax_value|
+ [tax_rate,
+ tax_value.format(with_currency: false)]
+ }
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/order_spec.rb b/spec/features/admin/order_spec.rb
new file mode 100644
index 0000000000..934b7f02f9
--- /dev/null
+++ b/spec/features/admin/order_spec.rb
@@ -0,0 +1,353 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+feature '
+ As an administrator
+ I want to create and edit orders
+', js: true do
+ include AuthenticationWorkflow
+ include WebHelper
+
+ let(:user) { create(:user) }
+ let(:product) { create(:simple_product) }
+ let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) }
+ let(:order_cycle) do
+ create(:simple_order_cycle, name: 'One', distributors: [distributor],
+ variants: [product.variants.first])
+ end
+
+ let(:order) do
+ create(:order_with_totals_and_distribution, user: user, distributor: distributor,
+ order_cycle: order_cycle, state: 'complete',
+ payment_state: 'balance_due')
+ end
+ let(:customer) { order.customer }
+
+ before do
+ # ensure order has a payment to capture
+ order.finalize!
+
+ create :check_payment, order: order, amount: order.total
+ end
+
+ def new_order_with_distribution(distributor, order_cycle)
+ visit spree.new_admin_order_path
+ expect(page).to have_selector('#s2id_order_distributor_id')
+ select2_select distributor.name, from: 'order_distributor_id'
+ select2_select order_cycle.name, from: 'order_order_cycle_id'
+ click_button 'Next'
+ end
+
+ scenario "creating an order with distributor and order cycle" do
+ distributor_disabled = create(:distributor_enterprise)
+ create(:simple_order_cycle, name: 'Two')
+
+ quick_login_as_admin
+ visit spree.admin_orders_path
+ click_link 'New Order'
+
+ # Distributors without an order cycle should be shown as disabled
+ open_select2('#s2id_order_distributor_id')
+ expect(page).to have_selector "ul.select2-results li.select2-result.select2-disabled",
+ text: distributor_disabled.name
+ close_select2('#s2id_order_distributor_id')
+
+ # Order cycle selector should be disabled
+ expect(page).to have_selector "#s2id_order_order_cycle_id.select2-container-disabled"
+
+ # The distributor selector should limit the order cycle selection to those for that distributor
+ select2_select distributor.name, from: 'order_distributor_id'
+ expect(page).to have_select2 'order_order_cycle_id', options: ['One (open)']
+ select2_select order_cycle.name, from: 'order_order_cycle_id'
+ click_button 'Next'
+
+ # it suppresses validation errors when setting distribution
+ expect(page).not_to have_selector '#errorExplanation'
+ expect(page).to have_content 'ADD PRODUCT'
+ targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
+ find('button.add_variant').click
+ page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
+ expect(page).to have_selector 'td', text: product.name
+
+ click_button 'Update'
+
+ expect(page).to have_selector 'h1', text: 'Customer Details'
+ o = Spree::Order.last
+ expect(o.distributor).to eq(distributor)
+ expect(o.order_cycle).to eq(order_cycle)
+ end
+
+ scenario "can add a product to an existing order" do
+ quick_login_as_admin
+ visit spree.edit_admin_order_path(order)
+
+ targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
+
+ find('button.add_variant').click
+
+ expect(page).to have_selector 'td', text: product.name
+ expect(order.line_items(true).map(&:product)).to include product
+ end
+
+ scenario "displays error when incorrect distribution for products is chosen" do
+ d = create(:distributor_enterprise)
+ oc = create(:simple_order_cycle, distributors: [d])
+
+ # Move the order back to the cart state
+ order.state = 'cart'
+ order.completed_at = nil
+ # A nil user keeps the order in the cart state
+ # Even if the edit page tries to automatically progress the order workflow
+ order.user = nil
+ order.save
+
+ quick_login_as_admin
+ visit spree.edit_admin_order_path(order)
+
+ expect(page).to have_select2 "order_distributor_id", with_options: [d.name]
+ select2_select d.name, from: 'order_distributor_id'
+ select2_select oc.name, from: 'order_order_cycle_id'
+
+ click_button 'Update And Recalculate Fees'
+ expect(page).to have_content "Distributor or order cycle " \
+ "cannot supply the products in your cart"
+ end
+
+ scenario "can't add products to an order outside the order's hub and order cycle" do
+ product = create(:simple_product)
+
+ quick_login_as_admin
+ visit spree.edit_admin_order_path(order)
+
+ expect(page).not_to have_select2 "add_variant_id", with_options: [product.name]
+ end
+
+ scenario "can't change distributor or order cycle once order has been finalized" do
+ quick_login_as_admin
+ visit spree.edit_admin_order_path(order)
+
+ expect(page).not_to have_select2 'order_distributor_id'
+ expect(page).not_to have_select2 'order_order_cycle_id'
+
+ expect(page).to have_selector 'p', text: "Distributor: #{order.distributor.name}"
+ expect(page).to have_selector 'p', text: "Order cycle: #{order.order_cycle.name}"
+ end
+
+ scenario "filling customer details" do
+ # Given a customer with an order, which includes their shipping and billing address
+
+ # We change the 1st order's address details, this way
+ # we validate that the original details (stored in customer) are picked up in the 2nd order
+ order.ship_address = create(:address, lastname: 'Ship')
+ order.bill_address = create(:address, lastname: 'Bill')
+ order.save!
+
+ # We set the existing ship method to delivery, this ship method will be used in the 2nd order
+ # Otherwise order_updater.shipping_address_from_distributor will set
+ # the 2nd order address to the distributor address
+ order.shipping_method.update_attribute :require_ship_address, true
+
+ # When I create a new order
+ quick_login_as user
+ new_order_with_distribution(distributor, order_cycle)
+ targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
+ find('button.add_variant').click
+ page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
+ click_button 'Update'
+
+ expect(page).to have_selector 'h1.page-title', text: "Customer Details"
+
+ # The customer selection partial should be visible
+ expect(page).to have_selector '#select-customer'
+
+ # And I select that customer's email address and save the order
+ targetted_select2_search customer.email, from: '#customer_search_override',
+ dropdown_css: '.select2-drop'
+ click_button 'Update'
+ expect(page).to have_selector "h1.page-title", text: "Customer Details"
+
+ # Then their addresses should be associated with the order
+ order = Spree::Order.last
+ expect(order.ship_address.lastname).to eq customer.ship_address.lastname
+ expect(order.bill_address.lastname).to eq customer.bill_address.lastname
+ end
+
+ context "as an enterprise manager" do
+ let(:coordinator1) { create(:distributor_enterprise) }
+ let(:coordinator2) { create(:distributor_enterprise) }
+ let!(:order_cycle1) { create(:order_cycle, coordinator: coordinator1) }
+ let!(:order_cycle2) { create(:simple_order_cycle, coordinator: coordinator2) }
+ let!(:supplier1) { order_cycle1.suppliers.first }
+ let!(:supplier2) { order_cycle1.suppliers.last }
+ let!(:distributor1) { order_cycle1.distributors.first }
+ let!(:distributor2) do
+ order_cycle1.distributors.reject{ |d| d == distributor1 }.last # ensure d1 != d2
+ end
+ let(:product) { order_cycle1.products.first }
+
+ before(:each) do
+ @enterprise_user = create_enterprise_user
+ @enterprise_user.enterprise_roles.build(enterprise: supplier1).save
+ @enterprise_user.enterprise_roles.build(enterprise: coordinator1).save
+ @enterprise_user.enterprise_roles.build(enterprise: distributor1).save
+
+ quick_login_as @enterprise_user
+ end
+
+ feature "viewing the edit page" do
+ let!(:shipping_method_for_distributor1) do
+ create(:shipping_method, name: "Normal", distributors: [distributor1])
+ end
+ let!(:order) do
+ create(:order_with_taxes, distributor: distributor1, ship_address: create(:address),
+ product_price: 110, tax_rate_amount: 0.1,
+ tax_rate_name: "Tax 1").tap do |record|
+ Spree::TaxRate.adjust(record)
+ record.update_shipping_fees!
+ end
+ end
+
+ background do
+ distributor1.update_attribute(:abn, '12345678')
+
+ visit spree.edit_admin_order_path(order)
+ end
+
+ scenario "verifying page contents" do
+ # shows a list of line_items
+ within('table.index tbody', match: :first) do
+ order.line_items.each do |item|
+ expect(page).to have_selector "td", match: :first, text: item.full_name
+ expect(page).to have_selector "td.item-price", text: item.single_display_amount
+ expect(page).to have_selector "input#quantity[value='#{item.quantity}']", visible: false
+ expect(page).to have_selector "td.item-total", text: item.display_amount
+ end
+ end
+
+ # shows the order items total
+ within('fieldset#order-total') do
+ expect(page).to have_selector "span.order-total", text: order.display_item_total
+ end
+
+ # shows the order non-tax adjustments
+ order.adjustments.eligible.each do |adjustment|
+ expect(page).to have_selector "td", match: :first, text: adjustment.label
+ expect(page).to have_selector "td.total", text: adjustment.display_amount
+ end
+
+ # shows the order total
+ expect(page).to have_selector "fieldset#order-total", text: order.display_total
+
+ # shows the order tax adjustments
+ within('fieldset', text: I18n.t('spree.admin.orders.form.line_item_adjustments').upcase) do
+ expect(page).to have_selector "td", match: :first, text: "Tax 1"
+ expect(page).to have_selector "td.total", text: Spree::Money.new(10)
+ end
+
+ # shows the dropdown menu" do
+ find("#links-dropdown .ofn-drop-down").click
+ within "#links-dropdown" do
+ expect(page).to have_link "Resend Confirmation",
+ href: spree.resend_admin_order_path(order)
+ expect(page).to have_link "Send Invoice", href: spree.invoice_admin_order_path(order)
+ expect(page).to have_link "Print Invoice", href: spree.print_admin_order_path(order)
+ expect(page).to have_link "Cancel Order", href: spree.fire_admin_order_path(order, e: 'cancel')
+ end
+ end
+
+ scenario "cannot split the order in different stock locations" do
+ # There's only 1 stock location in OFN,
+ # so the split functionality that comes with spree should be hidden
+ expect(page).to_not have_selector '.split-item'
+ end
+
+ context "with different shipping methods" do
+ let!(:different_shipping_method_for_distributor1) do
+ create(:shipping_method, name: "Different", distributors: [distributor1])
+ end
+ let!(:shipping_method_for_distributor2) do
+ create(:shipping_method, name: "Other", distributors: [distributor2])
+ end
+
+ scenario "can edit shipping method" do
+ visit spree.edit_admin_order_path(order)
+
+ expect(page).to_not have_content different_shipping_method_for_distributor1.name
+
+ find('.edit-method').click
+ expect(page).to have_select2 'selected_shipping_rate_id',
+ with_options: [
+ shipping_method_for_distributor1.name,
+ different_shipping_method_for_distributor1.name
+ ], without_options: [shipping_method_for_distributor2.name]
+ select2_select different_shipping_method_for_distributor1.name,
+ from: 'selected_shipping_rate_id'
+ find('.save-method').click
+
+ expect(page).to have_content different_shipping_method_for_distributor1.name
+ end
+ end
+
+ scenario "can edit tracking number" do
+ test_tracking_number = "ABCCBA"
+ expect(page).to_not have_content test_tracking_number
+
+ find('.edit-tracking').click
+ fill_in "tracking", with: test_tracking_number
+ find('.save-tracking').click
+
+ expect(page).to have_content test_tracking_number
+ end
+
+ scenario "editing shipping fees" do
+ click_link "Adjustments"
+ shipping_adjustment_tr_selector = "tr#spree_adjustment_#{order.adjustments.shipping.first.id}"
+ page.find("#{shipping_adjustment_tr_selector} td.actions a.icon-edit").click
+
+ fill_in "Amount", with: "5"
+ click_button "Continue"
+
+ expect(page.find("#{shipping_adjustment_tr_selector} td.amount")).to have_content "5.00"
+ end
+
+ context "when an included variant has been deleted" do
+ let!(:deleted_variant) do
+ order.line_items.first.variant.tap(&:delete)
+ end
+
+ it "still lists the variant in the order page" do
+ within ".stock-contents" do
+ expect(page).to have_content deleted_variant.product_and_full_name
+ end
+ end
+ end
+ end
+
+ scenario "creating an order with distributor and order cycle" do
+ new_order_with_distribution(distributor1, order_cycle1)
+
+ expect(page).to have_content 'ADD PRODUCT'
+ targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
+
+ find('button.add_variant').click
+ page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr"
+ expect(page).to have_selector 'td', text: product.name
+
+ expect(page).to have_select2 'order_distributor_id', with_options: [distributor1.name]
+ expect(page).to_not have_select2 'order_distributor_id', with_options: [distributor2.name]
+
+ expect(page).to have_select2 'order_order_cycle_id',
+ with_options: ["#{order_cycle1.name} (open)"]
+ expect(page).to_not have_select2 'order_order_cycle_id',
+ with_options: ["#{order_cycle2.name} (open)"]
+
+ click_button 'Update'
+
+ expect(page).to have_selector 'h1', text: 'Customer Details'
+ o = Spree::Order.last
+ expect(o.distributor).to eq distributor1
+ expect(o.order_cycle).to eq order_cycle1
+ end
+ end
+end
diff --git a/spec/features/admin/orders_spec.rb b/spec/features/admin/orders_spec.rb
index caa0a1613b..6713a7521f 100644
--- a/spec/features/admin/orders_spec.rb
+++ b/spec/features/admin/orders_spec.rb
@@ -1,5 +1,6 @@
+# frozen_string_literal: true
+
require "spec_helper"
-include ActionView::Helpers::NumberHelper
feature '
As an administrator
@@ -7,413 +8,87 @@ feature '
', js: true do
include AuthenticationWorkflow
include WebHelper
- include CheckoutHelper
- background do
- @user = create(:user)
- @product = create(:simple_product)
- @distributor = create(:distributor_enterprise, owner: @user, charges_sales_tax: true)
- @order_cycle = create(:simple_order_cycle, name: 'One', distributors: [@distributor], variants: [@product.variants.first])
-
- @order = create(:order_with_totals_and_distribution, user: @user, distributor: @distributor, order_cycle: @order_cycle, state: 'complete', payment_state: 'balance_due')
- @customer = create(:customer, enterprise: @distributor, email: @user.email, user: @user, ship_address: create(:address))
-
- # ensure order has a payment to capture
- @order.finalize!
-
- create :check_payment, order: @order, amount: @order.total
+ let(:user) { create(:user) }
+ let(:product) { create(:simple_product) }
+ let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) }
+ let(:order_cycle) do
+ create(:simple_order_cycle, name: 'One', distributors: [distributor],
+ variants: [product.variants.first])
end
- def new_order_with_distribution(distributor, order_cycle)
- visit 'admin/orders/new'
- expect(page).to have_selector('#s2id_order_distributor_id')
- select2_select distributor.name, from: 'order_distributor_id'
- select2_select order_cycle.name, from: 'order_order_cycle_id'
- click_button 'Next'
- end
-
- scenario "order cycles appear in descending order by close date on orders page" do
- create(:simple_order_cycle, name: 'Two', orders_close_at: 2.weeks.from_now)
- create(:simple_order_cycle, name: 'Four', orders_close_at: 4.weeks.from_now)
- create(:simple_order_cycle, name: 'Three', orders_close_at: 3.weeks.from_now)
-
- quick_login_as_admin
- visit 'admin/orders'
-
- open_select2('#s2id_q_order_cycle_id_in')
-
- expect(find('#q_order_cycle_id_in', visible: :all)[:innerHTML]).to have_content(/.*Four.*Three.*Two.*One/m)
- end
-
- scenario "creating an order with distributor and order cycle" do
- distributor_disabled = create(:distributor_enterprise)
- create(:simple_order_cycle, name: 'Two')
-
- quick_login_as_admin
-
- visit '/admin/orders'
- click_link 'New Order'
-
- # Distributors without an order cycle should be shown as disabled
- open_select2('#s2id_order_distributor_id')
- expect(page).to have_selector "ul.select2-results li.select2-result.select2-disabled", text: distributor_disabled.name
- close_select2('#s2id_order_distributor_id')
-
- # Order cycle selector should be disabled
- expect(page).to have_selector "#s2id_order_order_cycle_id.select2-container-disabled"
-
- # When we select a distributor, it should limit order cycle selection to those for that distributor
- select2_select @distributor.name, from: 'order_distributor_id'
- expect(page).to have_select2 'order_order_cycle_id', options: ['One (open)']
- select2_select @order_cycle.name, from: 'order_order_cycle_id'
- click_button 'Next'
-
- # it suppresses validation errors when setting distribution
- expect(page).not_to have_selector '#errorExplanation'
- expect(page).to have_content 'ADD PRODUCT'
- targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
- find('button.add_variant').click
- page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
- expect(page).to have_selector 'td', text: @product.name
-
- click_button 'Update'
-
- expect(page).to have_selector 'h1', text: 'Customer Details'
- o = Spree::Order.last
- expect(o.distributor).to eq(@distributor)
- expect(o.order_cycle).to eq(@order_cycle)
- end
-
- scenario "can add a product to an existing order" do
- quick_login_as_admin
- visit '/admin/orders'
-
- click_icon :edit
-
- targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
-
- find('button.add_variant').click
-
- expect(page).to have_selector 'td', text: @product.name
- expect(@order.line_items(true).map(&:product)).to include @product
- end
-
- scenario "displays error when incorrect distribution for products is chosen" do
- d = create(:distributor_enterprise)
- oc = create(:simple_order_cycle, distributors: [d])
-
- # Move the order back to the cart state
- @order.state = 'cart'
- @order.completed_at = nil
- # A nil user keeps the order in the cart state
- # Even if the edit page tries to automatically progress the order workflow
- @order.user = nil
- @order.save
-
- quick_login_as_admin
- visit '/admin/orders'
- uncheck 'Only show complete orders'
- page.find('a.icon-search').click
-
- click_icon :edit
- expect(page).to have_select2 "order_distributor_id", with_options: [d.name]
- select2_select d.name, from: 'order_distributor_id'
- select2_select oc.name, from: 'order_order_cycle_id'
-
- click_button 'Update And Recalculate Fees'
- expect(page).to have_content "Distributor or order cycle cannot supply the products in your cart"
- end
-
- scenario "can't add products to an order outside the order's hub and order cycle" do
- product = create(:simple_product)
-
- quick_login_as_admin
- visit '/admin/orders'
- page.find('td.actions a.icon-edit').click
-
- expect(page).not_to have_select2 "add_variant_id", with_options: [product.name]
- end
-
- scenario "can't change distributor or order cycle once order has been finalized" do
- quick_login_as_admin
- visit '/admin/orders'
- page.find('td.actions a.icon-edit').click
-
- expect(page).not_to have_select2 'order_distributor_id'
- expect(page).not_to have_select2 'order_order_cycle_id'
-
- expect(page).to have_selector 'p', text: "Distributor: #{@order.distributor.name}"
- expect(page).to have_selector 'p', text: "Order cycle: #{@order.order_cycle.name}"
- end
-
- scenario "filling customer details" do
- # Given a customer with an order, which includes their shipping and billing address
-
- # We change the 1st order's address details
- # This way we validate that the original details (stored in customer) are picked up in the 2nd order
- @order.ship_address = create(:address, lastname: 'Ship')
- @order.bill_address = create(:address, lastname: 'Bill')
- @order.save!
-
- # We set the existing shipping method to delivery, this shipping method will be used in the 2nd order
- # Otherwise order_updater.shipping_address_from_distributor will set the 2nd order address to the distributor address
- @order.shipping_method.update_attribute :require_ship_address, true
-
- # When I create a new order
- quick_login_as @user
- new_order_with_distribution(@distributor, @order_cycle)
- targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
- find('button.add_variant').click
- page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
- click_button 'Update'
-
- expect(page).to have_selector 'h1.page-title', text: "Customer Details"
-
- # The customer selection partial should be visible
- expect(page).to have_selector '#select-customer'
-
- # And I select that customer's email address and save the order
- targetted_select2_search @customer.email, from: '#customer_search_override', dropdown_css: '.select2-drop'
- click_button 'Update'
- expect(page).to have_selector "h1.page-title", text: "Customer Details"
-
- # Then their addresses should be associated with the order
- order = Spree::Order.last
- expect(order.ship_address.lastname).to eq @customer.ship_address.lastname
- expect(order.bill_address.lastname).to eq @customer.bill_address.lastname
- end
-
- scenario "capture payment from the orders index page" do
- quick_login_as_admin
-
- visit spree.admin_orders_path
- expect(page).to have_current_path spree.admin_orders_path
-
- # click the 'capture' link for the order
- page.find("[data-powertip=Capture]").click
-
- expect(page).to have_css "i.success"
- expect(page).to have_css "button.icon-road"
-
- # check the order was captured
- expect(@order.reload.payment_state).to eq "paid"
-
- # we should still be on the same page
- expect(page).to have_current_path spree.admin_orders_path
- end
-
- scenario "ship order from the orders index page" do
- @order.payments.first.capture!
- quick_login_as_admin
- visit spree.admin_orders_path
-
- page.find("[data-powertip=Ship]").click
-
- expect(page).to have_css "i.success"
- expect(@order.reload.shipments.any?(&:shipped?)).to be true
- end
-
- context "as an enterprise manager" do
- let(:coordinator1) { create(:distributor_enterprise) }
- let(:coordinator2) { create(:distributor_enterprise) }
- let!(:order_cycle1) { create(:order_cycle, coordinator: coordinator1) }
- let!(:order_cycle2) { create(:simple_order_cycle, coordinator: coordinator2) }
- let!(:supplier1) { order_cycle1.suppliers.first }
- let!(:supplier2) { order_cycle1.suppliers.last }
- let!(:distributor1) { order_cycle1.distributors.first }
- let!(:distributor2) { order_cycle1.distributors.reject{ |d| d == distributor1 }.last } # ensure d1 != d2
- let(:product) { order_cycle1.products.first }
-
- before(:each) do
- @enterprise_user = create_enterprise_user
- @enterprise_user.enterprise_roles.build(enterprise: supplier1).save
- @enterprise_user.enterprise_roles.build(enterprise: coordinator1).save
- @enterprise_user.enterprise_roles.build(enterprise: distributor1).save
-
- quick_login_as @enterprise_user
+ context "with a complete order" do
+ let(:order) do
+ create(:order_with_totals_and_distribution, user: user, distributor: distributor,
+ order_cycle: order_cycle,
+ state: 'complete', payment_state: 'balance_due')
end
- feature "viewing the edit page" do
- let!(:shipping_method_for_distributor1) { create(:shipping_method, name: "Normal", distributors: [distributor1]) }
- let!(:different_shipping_method_for_distributor1) { create(:shipping_method, name: "Different", distributors: [distributor1]) }
- let!(:shipping_method_for_distributor2) { create(:shipping_method, name: "Other", distributors: [distributor2]) }
+ scenario "order cycles appear in descending order by close date on orders page" do
+ create(:simple_order_cycle, name: 'Two', orders_close_at: 2.weeks.from_now)
+ create(:simple_order_cycle, name: 'Four', orders_close_at: 4.weeks.from_now)
+ create(:simple_order_cycle, name: 'Three', orders_close_at: 3.weeks.from_now)
- let!(:order) do
- create(:order_with_taxes, distributor: distributor1, ship_address: create(:address),
- product_price: 110, tax_rate_amount: 0.1,
- tax_rate_name: "Tax 1").tap do |record|
- Spree::TaxRate.adjust(record)
- record.update_shipping_fees!
- end
- end
+ quick_login_as_admin
+ visit 'admin/orders'
- background do
- Spree::Config[:enable_receipt_printing?] = true
- distributor1.update_attribute(:abn, '12345678')
+ open_select2('#s2id_q_order_cycle_id_in')
- visit spree.edit_admin_order_path(order)
- end
-
- scenario "shows a list of line_items" do
- within('table.index tbody', match: :first) do
- order.line_items.each do |item|
- expect(page).to have_selector "td", match: :first, text: item.full_name
- expect(page).to have_selector "td.item-price", text: item.single_display_amount
- expect(page).to have_selector "input#quantity[value='#{item.quantity}']", visible: false
- expect(page).to have_selector "td.item-total", text: item.display_amount
- end
- end
- end
-
- scenario "shows the order items total" do
- within('fieldset#order-total') do
- expect(page).to have_selector "span.order-total", text: order.display_item_total
- end
- end
-
- scenario "shows the order non-tax adjustments" do
- within('table.index tbody') do
- order.adjustments.eligible.each do |adjustment|
- expect(page).to have_selector "td", match: :first, text: adjustment.label
- expect(page).to have_selector "td.total", text: adjustment.display_amount
- end
- end
- end
-
- scenario "shows the order total" do
- expect(page).to have_selector "fieldset#order-total", text: order.display_total
- end
-
- scenario "shows the order tax adjustments" do
- within('fieldset', text: I18n.t('spree.admin.orders.form.line_item_adjustments').upcase) do
- expect(page).to have_selector "td", match: :first, text: "Tax 1"
- expect(page).to have_selector "td.total", text: Spree::Money.new(10)
- end
- end
-
- scenario "shows the dropdown menu" do
- find("#links-dropdown .ofn-drop-down").click
- within "#links-dropdown" do
- expect(page).to have_link "Resend Confirmation", href: spree.resend_admin_order_path(order)
- expect(page).to have_link "Send Invoice", href: spree.invoice_admin_order_path(order)
- expect(page).to have_link "Print Invoice", href: spree.print_admin_order_path(order)
- expect(page).to have_link "Cancel Order", href: spree.fire_admin_order_path(order, e: 'cancel')
- end
- end
-
- scenario "cannot split the order in different stock locations" do
- # There's only 1 stock location in OFN, so the split functionality that comes with spree should be hidden
- expect(page).to_not have_selector '.split-item'
- end
-
- scenario "can edit shipping method" do
- expect(page).to_not have_content different_shipping_method_for_distributor1.name
-
- find('.edit-method').click
- expect(page).to have_select2 'selected_shipping_rate_id', with_options: [shipping_method_for_distributor1.name, different_shipping_method_for_distributor1.name], without_options: [shipping_method_for_distributor2.name]
- select2_select different_shipping_method_for_distributor1.name, from: 'selected_shipping_rate_id'
- find('.save-method').click
-
- expect(page).to have_content different_shipping_method_for_distributor1.name
- end
-
- scenario "can edit tracking number" do
- test_tracking_number = "ABCCBA"
- expect(page).to_not have_content test_tracking_number
-
- find('.edit-tracking').click
- fill_in "tracking", with: test_tracking_number
- find('.save-tracking').click
-
- expect(page).to have_content test_tracking_number
- end
-
- scenario "can print an order's ticket" do
- find("#links-dropdown .ofn-drop-down").click
-
- ticket_window = window_opened_by do
- within('#links-dropdown') do
- click_link('Print Ticket')
- end
- end
-
- within_window ticket_window do
- accept_alert do
- print_data = page.evaluate_script('printData');
- elements_in_print_data =
- [
- order.distributor.name,
- order.distributor.address.address_part1,
- order.distributor.address.address_part2,
- order.distributor.contact.email,
- order.number,
- order.line_items.map { |line_item|
- [line_item.quantity.to_s,
- line_item.product.name,
- line_item.single_display_amount_with_adjustments.format(symbol: false, with_currency: false),
- line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)]
- },
- checkout_adjustments_for(order, exclude: [:line_item]).reject { |a| a.amount == 0 }.map { |adjustment|
- [raw(adjustment.label),
- display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)]
- },
- order.display_total.format(with_currency: false),
- display_checkout_taxes_hash(order).map { |tax_rate, tax_value|
- [tax_rate,
- tax_value.format(with_currency: false)]
- },
- display_checkout_total_less_tax(order).format(with_currency: false)
- ]
- expect(print_data.join).to include(*elements_in_print_data.flatten)
- end
- end
- end
-
- scenario "editing shipping fees" do
- click_link "Adjustments"
- page.find('td.actions a.icon-edit').click
-
- fill_in "Amount", with: "5"
- click_button "Continue"
-
- expect(page.find("td.amount")).to have_content "$5.00"
- end
-
- context "when an included variant has been deleted" do
- let!(:deleted_variant) do
- order.line_items.first.variant.tap(&:delete)
- end
-
- it "still lists the variant in the order page" do
- within ".stock-contents" do
- expect(page).to have_content deleted_variant.product_and_full_name
- end
- end
- end
+ expect(find('#q_order_cycle_id_in',
+ visible: :all)[:innerHTML]).to have_content(/.*Four.*Three.*Two/m)
end
- scenario "creating an order with distributor and order cycle" do
- new_order_with_distribution(distributor1, order_cycle1)
+ context "with a capturable order" do
+ before do
+ order.finalize! # ensure order has a payment to capture
+ create :check_payment, order: order, amount: order.total
+ end
- expect(page).to have_content 'ADD PRODUCT'
- targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
+ scenario "capture payment" do
+ quick_login_as_admin
- find('button.add_variant').click
- page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
- expect(page).to have_selector 'td', text: product.name
+ visit spree.admin_orders_path
+ expect(page).to have_current_path spree.admin_orders_path
- expect(page).to have_select2 'order_distributor_id', with_options: [distributor1.name]
- expect(page).to_not have_select2 'order_distributor_id', with_options: [distributor2.name]
+ # click the 'capture' link for the order
+ page.find("[data-powertip=Capture]").click
- expect(page).to have_select2 'order_order_cycle_id', with_options: ["#{order_cycle1.name} (open)"]
- expect(page).to_not have_select2 'order_order_cycle_id', with_options: ["#{order_cycle2.name} (open)"]
+ expect(page).to have_css "i.success"
+ expect(page).to have_css "button.icon-road"
- click_button 'Update'
+ # check the order was captured
+ expect(order.reload.payment_state).to eq "paid"
- expect(page).to have_selector 'h1', text: 'Customer Details'
- o = Spree::Order.last
- expect(o.distributor).to eq distributor1
- expect(o.order_cycle).to eq order_cycle1
+ # we should still be on the same page
+ expect(page).to have_current_path spree.admin_orders_path
+ end
+
+ scenario "ship order from the orders index page" do
+ order.payments.first.capture!
+ quick_login_as_admin
+ visit spree.admin_orders_path
+
+ page.find("[data-powertip=Ship]").click
+
+ expect(page).to have_css "i.success"
+ expect(order.reload.shipments.any?(&:shipped?)).to be true
+ end
+ end
+ end
+
+ context "with incomplete order" do
+ scenario "can edit order" do
+ incomplete_order = create(:order, distributor: distributor, order_cycle: order_cycle)
+
+ quick_login_as_admin
+
+ visit spree.admin_orders_path
+ uncheck 'Only show complete orders'
+ page.find('a.icon-search').click
+
+ click_icon :edit
+
+ expect(page).to have_current_path spree.edit_admin_order_path(incomplete_order)
end
end
end
diff --git a/spec/features/consumer/account_spec.rb b/spec/features/consumer/account_spec.rb
index 23494f6a2c..f6a205bd29 100644
--- a/spec/features/consumer/account_spec.rb
+++ b/spec/features/consumer/account_spec.rb
@@ -42,8 +42,14 @@ feature '
# Lists all other orders
expect(page).to have_content d1o1.number.to_s
expect(page).to have_content d1o2.number.to_s
+ expect(page).to have_link(distributor1.name,
+ href: "#{distributor1.permalink}/shop", count: 2)
expect(page).to have_content d2o1.number.to_s
+ expect(page).to have_link(distributor2.name,
+ href: "#{distributor2.permalink}/shop", count: 1)
expect(page).to have_content credit_order.number.to_s
+ expect(page).to have_link(distributor_credit.name,
+ href: "#{distributor_credit.permalink}/shop", count: 1)
# Viewing transaction history
click_link I18n.t('spree.users.show.tabs.transactions')
@@ -75,6 +81,8 @@ feature '
expect(page).to have_link d1o1.number, href: spree.order_path(d1o1)
expect(page).to have_link d1o2.number, href: spree.order_path(d1o2)
+ expect(page).to have_link(distributor1.name,
+ href: "#{distributor1.permalink}/shop", count: 2)
expect(page).to have_link I18n.t('spree.users.open_orders.cancel'), href: spree.cancel_order_path(d1o1)
expect(page).to have_link I18n.t('spree.users.open_orders.cancel'), href: spree.cancel_order_path(d1o2)
end
diff --git a/spec/features/consumer/groups_spec.rb b/spec/features/consumer/groups_spec.rb
index c59835c344..dc9a3e4b75 100644
--- a/spec/features/consumer/groups_spec.rb
+++ b/spec/features/consumer/groups_spec.rb
@@ -60,8 +60,8 @@ feature 'Groups', js: true do
let!(:group) { create(:enterprise_group, enterprises: [d1, d2], on_front_page: true) }
let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) }
let(:producer) { create(:supplier_enterprise) }
- let(:d1) { create(:distributor_enterprise) }
- let(:d2) { create(:distributor_enterprise) }
+ let(:d1) { create(:distributor_enterprise, with_payment_and_shipping: true) }
+ let(:d2) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:p1) { create(:simple_product, supplier: producer) }
let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) }
let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first }
diff --git a/spec/helpers/products_helper_spec.rb b/spec/helpers/products_helper_spec.rb
deleted file mode 100644
index 876c263eed..0000000000
--- a/spec/helpers/products_helper_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'spec_helper'
-
-module Spree
- describe ProductsHelper, type: :helper do
- it "displays variant price differences as absolute, not relative values" do
- variant = make_variant_stub(10.00, 10.00)
- expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(10.00)})")
-
- variant = make_variant_stub(10.00, 15.55)
- expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(15.55)})")
-
- variant = make_variant_stub(10.00, 5.55)
- expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(5.55)})")
- end
-
- private
-
- def make_variant_stub(product_price, variant_price)
- product = double(:product, price: product_price)
- variant = double(:variant, product: product, price: variant_price)
- variant
- end
- end
-end
diff --git a/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee b/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee
index 5724fe1353..1c860e8e91 100644
--- a/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee
+++ b/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee
@@ -51,9 +51,9 @@ describe "VariantOverridesCtrl", ->
it "adds products", ->
spyOn(VariantOverrides, "ensureDataFor")
expect(scope.products).toEqual []
- scope.addProducts ['a', 'b']
+ scope.addProducts { products: ['a', 'b'] }
expect(scope.products).toEqual ['a', 'b']
- scope.addProducts ['c', 'd']
+ scope.addProducts { products: ['c', 'd'] }
expect(scope.products).toEqual ['a', 'b', 'c', 'd']
expect(VariantOverrides.ensureDataFor).toHaveBeenCalled()
diff --git a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee
index a30eb4eeb8..2ffde63a3e 100644
--- a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee
+++ b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee
@@ -20,7 +20,6 @@ describe "CustomersCtrl", ->
{id: 109, name: "Australia", states: [{id: 55, name: "ACT", abbr: "ACT"}]}
]
-
inject ($controller, $rootScope, _CustomerResource_, $httpBackend) ->
scope = $rootScope
http = $httpBackend
diff --git a/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee b/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee
index 7886d8ddd6..2e7cfee530 100644
--- a/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee
+++ b/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee
@@ -36,9 +36,18 @@ describe "ordersCtrl", ->
'q[s]': 'completed_at desc'
}))
-
describe "using pagination", ->
it "changes the page", ->
$scope.changePage(2)
expect($scope.page).toEqual 2
expect(Orders.index).toHaveBeenCalled()
+
+ describe "sorting products", ->
+ it "sorts orders", ->
+ spyOn $scope, "fetchResults"
+
+ $scope.sortOptions.toggle('number')
+ $scope.$apply()
+
+ expect($scope.sorting).toEqual 'number asc'
+ expect($scope.fetchResults).toHaveBeenCalled()
diff --git a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee
index 4ff2f0d97a..d7e23b457b 100644
--- a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee
+++ b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee
@@ -3,10 +3,13 @@ describe 'Checkout service', ->
orderData = null
$httpBackend = null
Navigation = null
+ navigationSpy = null
flash = null
scope = null
FlashLoaderMock =
- loadFlash: (arg)->
+ loadFlash: (arg) ->
+ Loading =
+ clear: (arg)->
paymentMethods = [{
id: 99
test: "foo"
@@ -48,6 +51,7 @@ describe 'Checkout service', ->
module 'Darkswarm'
module ($provide)->
$provide.value "RailsFlashLoader", FlashLoaderMock
+ $provide.value "Loading", Loading
$provide.value "currentOrder", orderData
$provide.value "shippingMethods", shippingMethods
$provide.value "paymentMethods", paymentMethods
@@ -61,7 +65,7 @@ describe 'Checkout service', ->
scope.Checkout = Checkout
Navigation = $injector.get("Navigation")
flash = $injector.get("flash")
- spyOn(Navigation, "go") # Stubbing out writes to window.location
+ navigationSpy = spyOn(Navigation, "go") # Stubbing out writes to window.location
it "defaults to no shipping method", ->
expect(Checkout.order.shipping_method_id).toEqual null
@@ -116,12 +120,46 @@ describe 'Checkout service', ->
$httpBackend.flush()
expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith {error: "frogs"}
- it "puts errors into the scope", ->
- $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}}
+ it "puts errors into the scope when there is a flash messages", ->
+ $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}, flash: {error: "flash frogs"}}
Checkout.submit()
+
$httpBackend.flush()
expect(Checkout.errors).toEqual {error: "frogs"}
+ it "throws exception and sends generic flash message when there are errors but no flash message", ->
+ $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "broken response"}}
+ try
+ Checkout.submit()
+ $httpBackend.flush()
+ catch error
+ expect(error.data.errors.error).toBe("broken response")
+
+ expect(Checkout.errors).toEqual {}
+
+ it "throws an exception and sends a flash message to the flash service when reponse doesnt contain errors nor a flash message", ->
+ spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location
+ $httpBackend.expectPUT("/checkout.json").respond 400, "broken response"
+ try
+ Checkout.submit()
+ $httpBackend.flush()
+ catch error
+ expect(error.data).toBe("broken response")
+
+ expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") })
+
+ it "throws an exception and sends a flash message to the flash service when an exception is thrown while handling the error", ->
+ spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location
+ navigationSpy.and.callFake(-> throw "unexpected error")
+ $httpBackend.expectPUT("/checkout.json").respond 400, {path: 'path'}
+ try
+ Checkout.submit()
+ $httpBackend.flush()
+ catch error
+ expect(error).toBe("unexpected error")
+
+ expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") })
+
describe "when using the Stripe Connect gateway", ->
beforeEach inject ($injector, StripeElements) ->
Checkout.order.payment_method_id = 666
diff --git a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee
index 8b393a6aab..82c26397ca 100644
--- a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee
+++ b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee
@@ -1,5 +1,5 @@
describe "Enterprises service", ->
- Enterprises = null
+ Enterprises = $rootScope = null
CurrentHubMock = {}
Geo =
OK: 'ok'
@@ -36,15 +36,17 @@ describe "Enterprises service", ->
angular.module('Darkswarm').value('enterprises', enterprises)
angular.module('Darkswarm').value('taxons', taxons)
- inject ($injector)->
+ inject ($injector, _$rootScope_)->
Enterprises = $injector.get("Enterprises")
+ $rootScope = _$rootScope_
it "stores enterprises as id/object pairs", ->
expect(Enterprises.enterprises_by_id["1"]).toBe enterprises[0]
expect(Enterprises.enterprises_by_id["2"]).toBe enterprises[1]
it "stores enterprises as an array", ->
- expect(Enterprises.enterprises).toBe enterprises
+ $rootScope.$digest()
+ expect(Enterprises.enterprises).toEqual enterprises
it "puts the same objects in enterprises and enterprises_by_id", ->
expect(Enterprises.enterprises[0]).toBe Enterprises.enterprises_by_id["1"]
diff --git a/spec/jobs/subscription_confirm_job_spec.rb b/spec/jobs/subscription_confirm_job_spec.rb
index 3c433bf94d..a061d0fbd4 100644
--- a/spec/jobs/subscription_confirm_job_spec.rb
+++ b/spec/jobs/subscription_confirm_job_spec.rb
@@ -16,7 +16,7 @@ describe SubscriptionConfirmJob do
placed_at: 5.minutes.ago)
end
let!(:order) { proxy_order.initialise_order! }
- let(:proxy_orders) { job.send(:proxy_orders) }
+ let(:proxy_orders) { job.send(:unconfirmed_proxy_orders) }
before do
AdvanceOrderService.new(order).call!
@@ -80,8 +80,8 @@ describe SubscriptionConfirmJob do
before do
proxy_order.initialise_order!
- allow(job).to receive(:proxy_orders) { ProxyOrder.where(id: proxy_order.id) }
- allow(job).to receive(:process!)
+ allow(job).to receive(:unconfirmed_proxy_orders) { ProxyOrder.where(id: proxy_order.id) }
+ allow(job).to receive(:confirm_order!)
allow(job).to receive(:send_confirmation_summary_emails)
end
@@ -92,8 +92,7 @@ describe SubscriptionConfirmJob do
it "processes confirmable proxy_orders" do
job.perform
- expect(job).to have_received(:process!)
- expect(job.instance_variable_get(:@order)).to eq proxy_order.reload.order
+ expect(job).to have_received(:confirm_order!).with(proxy_order.reload.order)
end
it "sends a summary email" do
@@ -117,7 +116,7 @@ describe SubscriptionConfirmJob do
end
end
- describe "processing an order" do
+ describe "confirming an order" do
let(:shop) { create(:distributor_enterprise) }
let(:order_cycle1) { create(:simple_order_cycle, coordinator: shop) }
let(:order_cycle2) { create(:simple_order_cycle, coordinator: shop) }
@@ -128,35 +127,34 @@ describe SubscriptionConfirmJob do
before do
AdvanceOrderService.new(order).call!
- allow(job).to receive(:send_confirm_email).and_call_original
- job.instance_variable_set(:@order, order)
+ allow(job).to receive(:send_confirmation_email).and_call_original
setup_email
- expect(job).to receive(:record_order).with(order)
+ expect(job).to receive(:record_order)
end
context "when payments need to be processed" do
let(:payment_method) { create(:payment_method) }
- let(:payment) { double(:payment, amount: 10) }
+ let(:payment) { create(:payment, amount: 10) }
before do
- allow(order).to receive(:payment_total) { 0 }
- allow(order).to receive(:total) { 10 }
allow(order).to receive(:payment_required?) { true }
allow(order).to receive(:pending_payments) { [payment] }
end
context "and an error is added to the order when updating payments" do
- before { expect(job).to receive(:update_payment!) { order.errors.add(:base, "a payment error") } }
+ before do
+ expect(job).to receive(:setup_payment!) { |order| order.errors.add(:base, "a payment error") }
+ end
it "sends a failed payment email" do
expect(job).to receive(:send_failed_payment_email)
- expect(job).to_not receive(:send_confirm_email)
- job.send(:process!)
+ expect(job).to_not receive(:send_confirmation_email)
+ job.send(:confirm_order!, order)
end
end
context "and no errors are added when updating payments" do
- before { expect(job).to receive(:update_payment!) { true } }
+ before { expect(job).to receive(:setup_payment!) { true } }
context "when an error occurs while processing the payment" do
before do
@@ -165,8 +163,8 @@ describe SubscriptionConfirmJob do
it "sends a failed payment email" do
expect(job).to receive(:send_failed_payment_email)
- expect(job).to_not receive(:send_confirm_email)
- job.send(:process!)
+ expect(job).to_not receive(:send_confirmation_email)
+ job.send(:confirm_order!, order)
end
end
@@ -182,8 +180,8 @@ describe SubscriptionConfirmJob do
it "sends only a subscription confirm email, no regular confirmation emails" do
ActionMailer::Base.deliveries.clear
- expect{ job.send(:process!) }.to_not enqueue_job ConfirmOrderJob
- expect(job).to have_received(:send_confirm_email).once
+ expect{ job.send(:confirm_order!, order) }.to_not enqueue_job ConfirmOrderJob
+ expect(job).to have_received(:send_confirmation_email).once
expect(ActionMailer::Base.deliveries.count).to be 1
end
end
@@ -191,19 +189,18 @@ describe SubscriptionConfirmJob do
end
end
- describe "#send_confirm_email" do
+ describe "#send_confirmation_email" do
let(:order) { instance_double(Spree::Order) }
let(:mail_mock) { double(:mailer_mock, deliver: true) }
before do
- job.instance_variable_set(:@order, order)
allow(SubscriptionMailer).to receive(:confirmation_email) { mail_mock }
end
it "records a success and sends the email" do
expect(order).to receive(:update!)
expect(job).to receive(:record_success).with(order).once
- job.send(:send_confirm_email)
+ job.send(:send_confirmation_email, order)
expect(SubscriptionMailer).to have_received(:confirmation_email).with(order)
expect(mail_mock).to have_received(:deliver)
end
@@ -214,14 +211,13 @@ describe SubscriptionConfirmJob do
let(:mail_mock) { double(:mailer_mock, deliver: true) }
before do
- job.instance_variable_set(:@order, order)
allow(SubscriptionMailer).to receive(:failed_payment_email) { mail_mock }
end
it "records and logs an error and sends the email" do
expect(order).to receive(:update!)
expect(job).to receive(:record_and_log_error).with(:failed_payment, order).once
- job.send(:send_failed_payment_email)
+ job.send(:send_failed_payment_email, order)
expect(SubscriptionMailer).to have_received(:failed_payment_email).with(order)
expect(mail_mock).to have_received(:deliver)
end
diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb
index 29064b63f8..eb2e2f3cc9 100644
--- a/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb
+++ b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb
@@ -62,4 +62,26 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsRepor
expect(shipping_method_name_field).to eq shipping_method2.name
end
end
+
+ context 'when a variant override applies' do
+ let!(:order) do
+ create(:completed_order_with_totals, line_items_count: 1, user: customer.user,
+ customer: customer, distributor: distributor)
+ end
+ let(:overidden_sku) { 'magical_sku' }
+
+ before do
+ create(
+ :variant_override,
+ hub: distributor,
+ variant: order.line_items.first.variant,
+ sku: overidden_sku
+ )
+ end
+
+ it 'uses the sku from the variant override' do
+ sku_field = report_table.first[23]
+ expect(sku_field).to eq overidden_sku
+ end
+ end
end
diff --git a/spec/lib/open_food_network/proxy_order_syncer_spec.rb b/spec/lib/open_food_network/proxy_order_syncer_spec.rb
deleted file mode 100644
index 9b059d178f..0000000000
--- a/spec/lib/open_food_network/proxy_order_syncer_spec.rb
+++ /dev/null
@@ -1,400 +0,0 @@
-require 'open_food_network/proxy_order_syncer'
-
-module OpenFoodNetwork
- describe ProxyOrderSyncer do
- describe "initialization" do
- let!(:subscription) { create(:subscription) }
-
- it "raises an error when initialized with an object that is not a Subscription or an ActiveRecord::Relation" do
- expect{ ProxyOrderSyncer.new(subscription) }.to_not raise_error
- expect{ ProxyOrderSyncer.new(Subscription.where(id: subscription.id)) }.to_not raise_error
- expect{ ProxyOrderSyncer.new("something") }.to raise_error RuntimeError
- end
- end
-
- describe "#sync!" do
- let(:now) { Time.zone.now }
- let(:schedule) { create(:schedule) }
- let(:closed_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now) } # Closed
- let(:open_oc_closes_before_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now + 59.seconds) } # Open, but closes before begins at
- let(:open_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now + 90.seconds) } # Open & closes between begins at and ends at
- let(:upcoming_closes_before_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 59.seconds) } # Upcoming, but closes before begins at
- let(:upcoming_closes_on_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 1.minute) } # Upcoming & closes on begins at
- let(:upcoming_closes_on_ends_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 2.minutes) } # Upcoming & closes on ends at
- let(:upcoming_closes_after_ends_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 121.seconds) } # Upcoming & closes after ends at
- let(:subscription) { build(:subscription, schedule: schedule, begins_at: now + 1.minute, ends_at: now + 2.minutes) }
- let(:proxy_orders) { subscription.reload.proxy_orders }
- let(:order_cycles) { proxy_orders.map(&:order_cycle) }
- let(:syncer) { ProxyOrderSyncer.new(subscription) }
-
- context "when the subscription is not persisted" do
- before do
- oc # Ensure oc is created before we attempt to sync
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
- end
-
- context "and the schedule includes a closed oc (ie. closed before opens_at)" do
- let(:oc) { closed_oc }
- it "does not create a new proxy order for that oc" do
- expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes an open oc that closes before begins_at" do
- let(:oc) { open_oc_closes_before_begins_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes an open oc that closes between begins_at and ends_at" do
- let(:oc) { open_oc }
- it "creates a new proxy order for that oc" do
- expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes before begins_at" do
- let(:oc) { upcoming_closes_before_begins_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes on begins_at" do
- let(:oc) { upcoming_closes_on_begins_at_oc }
- it "creates a new proxy order for that oc" do
- expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes after ends_at" do
- let(:oc) { upcoming_closes_on_ends_at_oc }
- it "creates a new proxy order for that oc" do
- expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes after ends_at" do
- let(:oc) { upcoming_closes_after_ends_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
- end
-
- context "when the subscription is persisted" do
- before { expect(subscription.save!).to be true }
-
- context "when a proxy order exists" do
- let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: oc) }
-
- context "for an oc included in the relevant schedule" do
- context "and the proxy order has already been placed" do
- before { proxy_order.update_attributes(placed_at: 5.minutes.ago) }
-
- context "the oc is closed (ie. closed before opens_at)" do
- let(:oc) { closed_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the schedule includes an open oc that closes before begins_at" do
- let(:oc) { open_oc_closes_before_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is open and closes between begins_at and ends_at" do
- let(:oc) { open_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes before begins_at" do
- let(:oc) { upcoming_closes_before_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on begins_at" do
- let(:oc) { upcoming_closes_on_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on ends_at" do
- let(:oc) { upcoming_closes_on_ends_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes after ends_at" do
- let(:oc) { upcoming_closes_after_ends_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
- end
-
- context "and the proxy order has not already been placed" do
- context "the oc is closed (ie. closed before opens_at)" do
- let(:oc) { closed_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the schedule includes an open oc that closes before begins_at" do
- let(:oc) { open_oc_closes_before_begins_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is open and closes between begins_at and ends_at" do
- let(:oc) { open_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes before begins_at" do
- let(:oc) { upcoming_closes_before_begins_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on begins_at" do
- let(:oc) { upcoming_closes_on_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on ends_at" do
- let(:oc) { upcoming_closes_on_ends_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes after ends_at" do
- let(:oc) { upcoming_closes_after_ends_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
- end
- end
-
- context "for an oc not included in the relevant schedule" do
- let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: open_oc) }
- before do
- open_oc.schedule_ids = []
- expect(open_oc.save!).to be true
- end
-
- context "and the proxy order has already been placed" do
- before { proxy_order.update_attributes(placed_at: 5.minutes.ago) }
-
- context "the oc is closed (ie. closed before opens_at)" do
- let(:oc) { closed_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the schedule includes an open oc that closes before begins_at" do
- let(:oc) { open_oc_closes_before_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is open and closes between begins_at and ends_at" do
- let(:oc) { open_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes before begins_at" do
- let(:oc) { upcoming_closes_before_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on begins_at" do
- let(:oc) { upcoming_closes_on_begins_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on ends_at" do
- let(:oc) { upcoming_closes_on_ends_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes after ends_at" do
- let(:oc) { upcoming_closes_after_ends_at_oc }
- it "keeps the proxy order" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1)
- expect(proxy_orders).to include proxy_order
- end
- end
- end
-
- context "and the proxy order has not already been placed" do
- # This shouldn't really happen, but it is possible
- context "the oc is closed (ie. closed before opens_at)" do
- let(:oc) { closed_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- # This shouldn't really happen, but it is possible
- context "and the oc is open and closes between begins_at and ends_at" do
- let(:oc) { open_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes before begins_at" do
- let(:oc) { upcoming_closes_before_begins_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on begins_at" do
- let(:oc) { upcoming_closes_on_begins_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes on ends_at" do
- let(:oc) { upcoming_closes_on_ends_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
-
- context "and the oc is upcoming and closes after ends_at" do
- let(:oc) { upcoming_closes_after_ends_at_oc }
- it "removes the proxy order" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0)
- expect(proxy_orders).to_not include proxy_order
- end
- end
- end
- end
- end
-
- context "when a proxy order does not exist" do
- context "and the schedule includes a closed oc (ie. closed before opens_at)" do
- let!(:oc) { closed_oc }
- it "does not create a new proxy order for that oc" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes an open oc that closes before begins_at" do
- let(:oc) { open_oc_closes_before_begins_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes an open oc that closes between begins_at and ends_at" do
- let!(:oc) { open_oc }
- it "creates a new proxy order for that oc" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes before begins_at" do
- let!(:oc) { upcoming_closes_before_begins_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes on begins_at" do
- let!(:oc) { upcoming_closes_on_begins_at_oc }
- it "creates a new proxy order for that oc" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes on ends_at" do
- let!(:oc) { upcoming_closes_on_ends_at_oc }
- it "creates a new proxy order for that oc" do
- expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1)
- expect(order_cycles).to include oc
- end
- end
-
- context "and the schedule includes upcoming oc that closes after ends_at" do
- let!(:oc) { upcoming_closes_after_ends_at_oc }
- it "does not create a new proxy order for that oc" do
- expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0)
- expect(order_cycles).to_not include oc
- end
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/open_food_network/subscription_payment_updater_spec.rb b/spec/lib/open_food_network/subscription_payment_updater_spec.rb
deleted file mode 100644
index 77be81020e..0000000000
--- a/spec/lib/open_food_network/subscription_payment_updater_spec.rb
+++ /dev/null
@@ -1,216 +0,0 @@
-require 'spec_helper'
-require 'open_food_network/subscription_payment_updater'
-
-module OpenFoodNetwork
- describe SubscriptionPaymentUpdater do
- let(:order) { create(:order) }
- let(:updater) { OpenFoodNetwork::SubscriptionPaymentUpdater.new(order) }
-
- describe "#payment" do
- context "when only one payment exists on the order" do
- let!(:payment) { create(:payment, order: order) }
-
- context "where the payment is pending" do
- it { expect(updater.send(:payment)).to eq payment }
- end
-
- context "where the payment is failed" do
- before { payment.update_attribute(:state, 'failed') }
- it { expect(updater.send(:payment)).to be nil }
- end
- end
-
- context "when more that one payment exists on the order" do
- let!(:payment1) { create(:payment, order: order) }
- let!(:payment2) { create(:payment, order: order) }
-
- context "where more than one payment is pending" do
- it { expect([payment1, payment2]).to include updater.send(:payment) }
- end
-
- context "where only one payment is pending" do
- before { payment1.update_attribute(:state, 'failed') }
- it { expect(updater.send(:payment)).to eq payment2 }
- end
-
- context "where no payments are pending" do
- before do
- payment1.update_attribute(:state, 'failed')
- payment2.update_attribute(:state, 'failed')
- end
-
- it { expect(updater.send(:payment)).to be nil }
- end
- end
- end
-
- describe "#update!" do
- let!(:payment){ create(:payment, amount: 10) }
-
- context "when no pending payments are present" do
- let(:payment_method) { create(:payment_method) }
- let(:subscription) { double(:subscription, payment_method_id: payment_method.id) }
-
- before do
- allow(order).to receive(:pending_payments).once { [] }
- allow(order).to receive(:outstanding_balance) { 5 }
- allow(order).to receive(:subscription) { subscription }
- end
-
- it "creates a new payment on the order" do
- expect{ updater.update! }.to change(Spree::Payment, :count).by(1)
- expect(order.payments.first.amount).to eq 5
- end
- end
-
- context "when a payment is present" do
- before { allow(order).to receive(:pending_payments).once { [payment] } }
-
- context "when a credit card is not required" do
- before do
- allow(updater).to receive(:card_required?) { false }
- expect(updater).to_not receive(:card_available?)
- expect(updater).to_not receive(:ensure_credit_card)
- end
-
- context "when the payment total doesn't match the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 5 } }
- it "updates the payment total to reflect the outstanding balance" do
- expect{ updater.update! }.to change(payment, :amount).from(10).to(5)
- end
- end
-
- context "when the payment total matches the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 10 } }
-
- it "does nothing" do
- expect{ updater.update! }.to_not change(payment, :amount).from(10)
- end
- end
- end
-
- context "when a credit card is required" do
- before do
- expect(updater).to receive(:card_required?) { true }
- end
-
- context "and the payment source is not a credit card" do
- before { expect(updater).to receive(:card_set?) { false } }
-
- context "and no default credit card has been set by the customer" do
- before do
- allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) }
- end
-
- it "adds an error to the order and does not update the payment" do
- expect(payment).to_not receive(:update_attributes)
- expect{ updater.update! }.to change(order.errors[:base], :count).from(0).to(1)
- end
- end
-
- context "and the customer has not authorised the shop to charge to credit cards" do
- before do
- allow(order).to receive(:user) { instance_double(Spree::User, default_card: create(:credit_card)) }
- allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: false) }
- end
-
- it "adds an error to the order and does not update the payment" do
- expect(payment).to_not receive(:update_attributes)
- expect{ updater.update! }.to change(order.errors[:base], :count).from(0).to(1)
- end
- end
-
- context "and an authorised default credit card is available to charge" do
- before do
- allow(order).to receive(:user) { instance_double(Spree::User, default_card: create(:credit_card)) }
- allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: true) }
- end
-
- context "when the payment total doesn't match the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 5 } }
- it "updates the payment total to reflect the outstanding balance" do
- expect{ updater.update! }.to change(payment, :amount).from(10).to(5)
- end
- end
-
- context "when the payment total matches the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 10 } }
-
- it "does nothing" do
- expect{ updater.update! }.to_not change(payment, :amount).from(10)
- end
- end
- end
- end
-
- context "and the payment source is already a credit card" do
- before { expect(updater).to receive(:card_set?) { true } }
-
- context "when the payment total doesn't match the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 5 } }
- it "updates the payment total to reflect the outstanding balance" do
- expect{ updater.update! }.to change(payment, :amount).from(10).to(5)
- end
- end
-
- context "when the payment total matches the outstanding balance on the order" do
- before { allow(order).to receive(:outstanding_balance) { 10 } }
-
- it "does nothing" do
- expect{ updater.update! }.to_not change(payment, :amount).from(10)
- end
- end
- end
- end
- end
- end
-
- describe "#ensure_credit_card" do
- let!(:payment) { create(:payment, source: nil) }
- before { allow(updater).to receive(:payment) { payment } }
-
- context "when no default credit card is found" do
- before do
- allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) }
- end
-
- it "returns false and down not update the payment source" do
- expect do
- expect(updater.send(:ensure_credit_card)).to be false
- end.to_not change(payment, :source).from(nil)
- end
- end
-
- context "when a default credit card is found" do
- let(:credit_card) { create(:credit_card) }
- before do
- allow(order).to receive(:user) { instance_double(Spree::User, default_card: credit_card) }
- end
-
- context "and charge have not been authorised by the customer" do
- before do
- allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: false) }
- end
-
- it "returns false and does not update the payment source" do
- expect do
- expect(updater.send(:ensure_credit_card)).to be false
- end.to_not change(payment, :source).from(nil)
- end
- end
-
- context "and charges have been authorised by the customer" do
- before do
- allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: true) }
- end
-
- it "returns true and stores the credit card as the payment source" do
- expect do
- expect(updater.send(:ensure_credit_card)).to be true
- end.to change(payment, :source_id).from(nil).to(credit_card.id)
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/open_food_network/subscription_summarizer_spec.rb b/spec/lib/open_food_network/subscription_summarizer_spec.rb
deleted file mode 100644
index a0d2b3f7bf..0000000000
--- a/spec/lib/open_food_network/subscription_summarizer_spec.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-require 'spec_helper'
-require 'open_food_network/subscription_summarizer'
-
-module OpenFoodNetwork
- describe SubscriptionSummarizer do
- let(:order) { create(:order) }
- let(:summarizer) { OpenFoodNetwork::SubscriptionSummarizer.new }
-
- before { allow(Rails.logger).to receive(:info) }
-
- describe "#summary_for" do
- let(:order) { double(:order, distributor_id: 123) }
-
- context "when a summary for the order's distributor doesn't already exist" do
- it "initializes a new summary object, and returns it" do
- expect(summarizer.instance_variable_get(:@summaries).count).to be 0
- summary = summarizer.send(:summary_for, order)
- expect(summary.shop_id).to be 123
- expect(summarizer.instance_variable_get(:@summaries).count).to be 1
- end
- end
-
- context "when a summary for the order's distributor already exists" do
- let(:summary) { double(:summary) }
-
- before do
- summarizer.instance_variable_set(:@summaries, 123 => summary)
- end
-
- it "returns the existing summary object" do
- expect(summarizer.instance_variable_get(:@summaries).count).to be 1
- expect(summarizer.send(:summary_for, order)).to eq summary
- expect(summarizer.instance_variable_get(:@summaries).count).to be 1
- end
- end
- end
-
- describe "recording events" do
- let(:order) { double(:order) }
- let(:summary) { double(:summary) }
- before { allow(summarizer).to receive(:summary_for).with(order) { summary } }
-
- describe "#record_order" do
- it "requests a summary for the order and calls #record_order on it" do
- expect(summary).to receive(:record_order).with(order).once
- summarizer.record_order(order)
- end
- end
-
- describe "#record_success" do
- it "requests a summary for the order and calls #record_success on it" do
- expect(summary).to receive(:record_success).with(order).once
- summarizer.record_success(order)
- end
- end
-
- describe "#record_issue" do
- it "requests a summary for the order and calls #record_issue on it" do
- expect(order).to receive(:id)
- expect(summary).to receive(:record_issue).with(:type, order, "message").once
- summarizer.record_issue(:type, order, "message")
- end
- end
-
- describe "#record_and_log_error" do
- before do
- allow(order).to receive(:number) { "123" }
- end
-
- context "when errors exist on the order" do
- before do
- allow(order).to receive(:errors) { double(:errors, any?: true, full_messages: ["Some error"]) }
- end
-
- it "sends error info to the rails logger and calls #record_issue on itself with an error message" do
- expect(summarizer).to receive(:record_issue).with(:processing, order, "Errors: Some error")
- summarizer.record_and_log_error(:processing, order)
- end
- end
-
- context "when no errors exist on the order" do
- before do
- allow(order).to receive(:errors) { double(:errors, any?: false) }
- end
-
- it "falls back to calling record_issue" do
- expect(summarizer).to receive(:record_issue).with(:processing, order)
- summarizer.record_and_log_error(:processing, order)
- end
- end
- end
- end
-
- describe "#send_placement_summary_emails" do
- let(:summary1) { double(:summary) }
- let(:summary2) { double(:summary) }
- let(:summaries) { { 1 => summary1, 2 => summary2 } }
- let(:mail_mock) { double(:mail, deliver: true) }
-
- before do
- summarizer.instance_variable_set(:@summaries, summaries)
- end
-
- it "sends a placement summary email for each summary" do
- expect(SubscriptionMailer).to receive(:placement_summary_email).twice { mail_mock }
- summarizer.send_placement_summary_emails
- end
- end
-
- describe "#send_confirmation_summary_emails" do
- let(:summary1) { double(:summary) }
- let(:summary2) { double(:summary) }
- let(:summaries) { { 1 => summary1, 2 => summary2 } }
- let(:mail_mock) { double(:mail, deliver: true) }
-
- before do
- summarizer.instance_variable_set(:@summaries, summaries)
- end
-
- it "sends a placement summary email for each summary" do
- expect(SubscriptionMailer).to receive(:confirmation_summary_email).twice { mail_mock }
- summarizer.send_confirmation_summary_emails
- end
- end
- end
-end
diff --git a/spec/lib/open_food_network/subscription_summary_spec.rb b/spec/lib/open_food_network/subscription_summary_spec.rb
deleted file mode 100644
index f5b0cd8d71..0000000000
--- a/spec/lib/open_food_network/subscription_summary_spec.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-require 'open_food_network/subscription_summary'
-
-module OpenFoodNetwork
- describe SubscriptionSummary do
- let(:summary) { OpenFoodNetwork::SubscriptionSummary.new(123) }
-
- describe "#initialize" do
- it "initializes instance variables: shop_id, order_count, success_count and issues" do
- expect(summary.shop_id).to be 123
- expect(summary.order_count).to be 0
- expect(summary.success_count).to be 0
- expect(summary.issues).to be_a Hash
- end
- end
-
- describe "#record_order" do
- let(:order) { double(:order, id: 37) }
- it "adds the order id to the order_ids array" do
- summary.record_order(order)
- expect(summary.instance_variable_get(:@order_ids)).to eq [order.id]
- end
- end
-
- describe "#record_success" do
- let(:order) { double(:order, id: 37) }
- it "adds the order id to the success_ids array" do
- summary.record_success(order)
- expect(summary.instance_variable_get(:@success_ids)).to eq [order.id]
- end
- end
-
- describe "#record_issue" do
- let(:order) { double(:order, id: 1) }
-
- context "when no issues of the same type have been recorded yet" do
- it "adds a new type to the issues hash, and stores a new issue against it" do
- summary.record_issue(:some_type, order, "message")
- expect(summary.issues.keys).to include :some_type
- expect(summary.issues[:some_type][order.id]).to eq "message"
- end
- end
-
- context "when an issue of the same type has already been recorded" do
- let(:existing_issue) { double(:existing_issue) }
-
- before { summary.issues[:some_type] = [existing_issue] }
-
- it "stores a new issue against the existing type" do
- summary.record_issue(:some_type, order, "message")
- expect(summary.issues[:some_type]).to include existing_issue
- expect(summary.issues[:some_type][order.id]).to eq "message"
- end
- end
- end
-
- describe "#order_count" do
- let(:order_ids) { [1, 2, 3, 4, 5, 6, 7] }
- it "counts the number of items in the order_ids instance_variable" do
- summary.instance_variable_set(:@order_ids, order_ids)
- expect(summary.order_count).to be 7
- end
- end
-
- describe "#success_count" do
- let(:success_ids) { [1, 2, 3, 4, 5, 6, 7] }
- it "counts the number of items in the success_ids instance_variable" do
- summary.instance_variable_set(:@success_ids, success_ids)
- expect(summary.success_count).to be 7
- end
- end
-
- describe "#issue_count" do
- let(:order_ids) { [1, 3, 5, 7, 9] }
- let(:success_ids) { [1, 2, 3, 4, 5] }
-
- it "counts the number of items in order_ids that are not in success_ids" do
- summary.instance_variable_set(:@order_ids, order_ids)
- summary.instance_variable_set(:@success_ids, success_ids)
- expect(summary.issue_count).to be 2 # 7 & 9
- end
- end
-
- describe "#orders_affected_by" do
- let(:order1) { create(:order) }
- let(:order2) { create(:order) }
-
- before do
- allow(summary).to receive(:unrecorded_ids) { [order1.id] }
- allow(summary).to receive(:issues) { { failure: { order2.id => "A message" } } }
- end
-
- context "when the issue type is :other" do
- let(:orders) { summary.orders_affected_by(:other) }
-
- it "returns orders specified by unrecorded_ids" do
- expect(orders).to include order1
- expect(orders).to_not include order2
- end
- end
-
- context "when the issue type is :other" do
- let(:orders) { summary.orders_affected_by(:failure) }
-
- it "returns orders specified by the relevant issue hash" do
- expect(orders).to include order2
- expect(orders).to_not include order1
- end
- end
- end
-
- describe "#unrecorded_ids" do
- let(:issues) { { type: { 7 => "message", 8 => "message" } } }
-
- before do
- summary.instance_variable_set(:@order_ids, [1, 3, 5, 7, 9])
- summary.instance_variable_set(:@success_ids, [1, 2, 3, 4, 5])
- summary.instance_variable_set(:@issues, issues)
- end
-
- it "returns order_ids that are not marked as an issue or a success" do
- expect(summary.unrecorded_ids).to eq [9]
- end
- end
- end
-end
diff --git a/spec/mailers/producer_mailer_spec.rb b/spec/mailers/producer_mailer_spec.rb
index c74998c3ab..2449d450c0 100644
--- a/spec/mailers/producer_mailer_spec.rb
+++ b/spec/mailers/producer_mailer_spec.rb
@@ -101,6 +101,19 @@ describe ProducerMailer, type: :mailer do
end.to change(ActionMailer::Base.deliveries, :count).by(0)
end
+ it "shows a deleted variant's full name" do
+ variant = p1.variants.first
+ full_name = variant.full_name
+ variant.delete
+
+ expect(mail.body.encoded).to include(full_name)
+ end
+
+ it 'shows deleted products' do
+ p1.delete
+ expect(mail.body.encoded).to include(p1.name)
+ end
+
private
def body_lines_including(mail, s)
diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb
deleted file mode 100644
index a39d5fd609..0000000000
--- a/spec/models/producer_property_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-require 'spec_helper'
-
-describe ProducerProperty do
- let(:producer) { create(:supplier_enterprise) }
- let(:pp) { producer.producer_properties.first }
-
- before do
- producer.set_producer_property 'Organic Certified', 'NASAA 54321'
- end
-
- describe ".currently_sold_by and .ever_sold_by" do
- let!(:shop) { create(:distributor_enterprise) }
- let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) }
- let(:product) { create(:simple_product, supplier: producer) }
- let(:producer_other) { create(:supplier_enterprise) }
- let(:product_other) { create(:simple_product, supplier: producer_other) }
- let(:pp_other) { producer_other.producer_properties.first }
-
- before do
- producer_other.set_producer_property 'Spiffy', 'Ya'
- end
-
- describe "with an associated producer property" do
- it "returns the producer property" do
- expect(ProducerProperty.currently_sold_by(shop)).to eq [pp]
- expect(ProducerProperty.ever_sold_by(shop)).to eq [pp]
- end
- end
-
- describe "with a producer property for a producer not carried by that shop" do
- let!(:exchange) { create(:exchange, order_cycle: oc, incoming: true, sender: producer_other, receiver: oc.coordinator) }
-
- it "doesn't return the producer property" do
- expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other
- expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other
- end
- end
-
- describe "with a producer property for a product in a different shop" do
- let(:shop_other) { create(:distributor_enterprise) }
- let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) }
- let!(:exchange) { create(:exchange, order_cycle: oc, incoming: false, sender: oc.coordinator, receiver: shop_other, variants: [product_other.variants.first]) }
-
- it "doesn't return the producer property" do
- expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other
- expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other
- end
- end
-
- describe "with a producer property for a product in a closed order cycle" do
- before do
- oc.update_attributes! orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago
- end
-
- it "doesn't return the producer property for .currently_sold_by" do
- expect(ProducerProperty.currently_sold_by(shop)).not_to include pp
- end
-
- it "returns the producer property for .ever_sold_by" do
- expect(ProducerProperty.ever_sold_by(shop)).to include pp
- end
- end
-
- describe "with a duplicate producer property" do
- let(:product2) { create(:simple_product, supplier: producer) }
- let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) }
-
- it "doesn't return duplicates" do
- expect(ProducerProperty.currently_sold_by(shop).to_a.size).to eq 1
- expect(ProducerProperty.ever_sold_by(shop).to_a.size).to eq 1
- end
- end
- end
-end
diff --git a/spec/models/spree/calculator/price_sack_spec.rb b/spec/models/spree/calculator/price_sack_spec.rb
index 9b0a38d0e8..921b657f88 100644
--- a/spec/models/spree/calculator/price_sack_spec.rb
+++ b/spec/models/spree/calculator/price_sack_spec.rb
@@ -8,11 +8,11 @@ describe Spree::Calculator::PriceSack do
calculator.preferred_discount_amount = 1
calculator
end
-
let(:line_item) { build(:line_item, price: price, quantity: 2) }
context 'when the order amount is below preferred minimal' do
let(:price) { 2 }
+
it "uses the preferred normal amount" do
expect(calculator.compute(line_item)).to eq(10)
end
@@ -20,11 +20,35 @@ describe Spree::Calculator::PriceSack do
context 'when the order amount is above preferred minimal' do
let(:price) { 6 }
+
it "uses the preferred discount amount" do
expect(calculator.compute(line_item)).to eq(1)
end
end
+ context "preferred discount amount is float" do
+ before do
+ calculator.preferred_normal_amount = 10.4
+ calculator.preferred_discount_amount = 1.2
+ end
+
+ context 'when the order amount is below preferred minimal' do
+ let(:price) { 2 }
+
+ it "uses the float preferred normal amount" do
+ expect(calculator.compute(line_item)).to eq(10.4)
+ end
+ end
+
+ context 'when the order amount is above preferred minimal' do
+ let(:price) { 6 }
+
+ it "uses the float preferred discount amount" do
+ expect(calculator.compute(line_item)).to eq(1.2)
+ end
+ end
+ end
+
context "extends LocalizedNumber" do
it_behaves_like "a model using the LocalizedNumber module", [:preferred_minimal_amount, :preferred_normal_amount, :preferred_discount_amount]
end
diff --git a/spec/models/spree/property_spec.rb b/spec/models/spree/property_spec.rb
deleted file mode 100644
index a155cbfa45..0000000000
--- a/spec/models/spree/property_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-require 'spec_helper'
-
-module Spree
- describe Property do
- describe "scopes" do
- describe ".applied_by" do
- let(:producer) { create(:supplier_enterprise) }
- let(:producer_other) { create(:supplier_enterprise) }
- let(:product) { create(:simple_product, supplier: producer) }
- let(:product_other_producer) { create(:simple_product, supplier: producer_other) }
- let(:product_other_property) { create(:simple_product, supplier: producer) }
- let(:property) { product.properties.last }
- let(:property_other) { product_other_producer.properties.last }
-
- before do
- product.set_property 'Organic', 'NASAA 12345'
- product_other_property.set_property 'Organic', 'NASAA 12345'
- product_other_producer.set_property 'Biodynamic', 'ASDF 1234'
- end
-
- it "returns properties applied to supplied products" do
- expect(Spree::Property.applied_by(producer)).to eq [property]
- end
-
- it "doesn't return properties not applied" do
- expect(Spree::Property.applied_by(producer)).not_to include property_other
- end
-
- it "doesn't return duplicates" do
- expect(Spree::Property.applied_by(producer).to_a.size).to eq 1
- end
- end
-
- describe ".currently_sold_by and .ever_sold_by" do
- let!(:shop) { create(:distributor_enterprise) }
- let!(:shop_other) { create(:distributor_enterprise) }
- let!(:product) { create(:simple_product) }
- let!(:product_other_ex) { create(:simple_product) }
- let!(:product_no_oc) { create(:simple_product) }
- let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) }
- let!(:exchange_other_shop) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: shop_other, variants: [product_other_ex.variants.first]) }
- let(:property) { product.properties.last }
- let(:property_other_ex) { product_other_ex.properties.last }
- let(:property_no_oc) { product_no_oc.properties.last }
-
- before do
- product.set_property 'Organic', 'NASAA 12345'
- product_other_ex.set_property 'Biodynamic', 'ASDF 12345'
- product_no_oc.set_property 'Shiny', 'Very'
- end
-
- it "returns the property" do
- expect(Property.currently_sold_by(shop)).to eq [property]
- expect(Property.ever_sold_by(shop)).to eq [property]
- end
-
- it "doesn't return the property from another exchange" do
- expect(Property.currently_sold_by(shop)).not_to include property_other_ex
- expect(Property.ever_sold_by(shop)).not_to include property_other_ex
- end
-
- it "doesn't return the property with no order cycle" do
- expect(Property.currently_sold_by(shop)).not_to include property_no_oc
- expect(Property.ever_sold_by(shop)).not_to include property_no_oc
- end
-
- describe "closed order cyces" do
- let!(:product_closed_oc) { create(:simple_product) }
- let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) }
- let(:property_closed_oc) { product_closed_oc.properties.last }
-
- before { product_closed_oc.set_property 'Spiffy', 'Ooh yeah' }
-
- it "doesn't return the property for .currently_sold_by" do
- expect(Property.currently_sold_by(shop)).not_to include property_closed_oc
- end
-
- it "returns the property for .ever_sold_by" do
- expect(Property.ever_sold_by(shop)).to include property_closed_oc
- end
- end
-
- context "with another product in the order cycle" do
- let!(:product2) { create(:simple_product) }
- let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) }
-
- before do
- product2.set_property 'Organic', 'NASAA 12345'
- end
-
- it "doesn't return duplicates" do
- expect(Property.currently_sold_by(shop).to_a.size).to eq 1
- expect(Property.ever_sold_by(shop).to_a.size).to eq 1
- end
- end
- end
- end
- end
-end
diff --git a/spec/performance/proxy_order_syncer_spec.rb b/spec/performance/proxy_order_syncer_spec.rb
deleted file mode 100644
index 95678c68a2..0000000000
--- a/spec/performance/proxy_order_syncer_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-require 'open_food_network/proxy_order_syncer'
-
-module OpenFoodNetwork
- describe ProxyOrderSyncer, performance: true do
- let(:start) { Time.zone.now.beginning_of_day }
- let!(:schedule) { create(:schedule, order_cycles: order_cycles) }
-
- let!(:order_cycles) do
- Array.new(10) do |i|
- create(:simple_order_cycle, orders_open_at: start + i.days,
- orders_close_at: start + (i + 1).days )
- end
- end
-
- let!(:subscriptions) do
- Array.new(150) do |_i|
- create(:subscription, schedule: schedule, begins_at: start, ends_at: start + 10.days)
- end
- Subscription.where(schedule_id: schedule)
- end
-
- context "measuring performance for initialisation" do
- it "reports the average run time for adding 10 OCs to 150 subscriptions" do
- expect(ProxyOrder.count).to be 0
- times = []
- 10.times do
- syncer = ProxyOrderSyncer.new(subscriptions.reload)
-
- t1 = Time.zone.now
- syncer.sync!
- t2 = Time.zone.now
- diff = t2 - t1
- times << diff
- puts diff.round(2)
-
- expect(ProxyOrder.count).to be 1500
- ProxyOrder.destroy_all
- end
- puts "AVG: #{(times.sum / times.count).round(2)}"
- end
- end
-
- context "measuring performance for removal" do
- it "reports the average run time for removing 8 OCs from 150 subscriptions" do
- times = []
- 10.times do
- syncer = ProxyOrderSyncer.new(subscriptions.reload)
- syncer.sync!
- expect(ProxyOrder.count).to be 1500
- subscriptions.update_all(begins_at: start + 8.days + 1.minute)
- syncer = ProxyOrderSyncer.new(subscriptions.reload)
-
- t1 = Time.zone.now
- syncer.sync!
- t2 = Time.zone.now
- diff = t2 - t1
- times << diff
- puts diff.round(2)
-
- expect(ProxyOrder.count).to be 300
- subscriptions.update_all(begins_at: start)
- end
- puts "AVG: #{(times.sum / times.count).round(2)}"
- end
- end
- end
-end
diff --git a/spec/serializers/api/admin/customer_serializer_spec.rb b/spec/serializers/api/admin/customer_serializer_spec.rb
index 02c97e3948..0d9b1625d9 100644
--- a/spec/serializers/api/admin/customer_serializer_spec.rb
+++ b/spec/serializers/api/admin/customer_serializer_spec.rb
@@ -1,12 +1,16 @@
require 'spec_helper'
describe Api::Admin::CustomerSerializer do
- let(:customer) { create(:customer, tag_list: "one, two, three") }
+ let(:tag_list) { ["one", "two", "three"] }
+ let(:customer) { create(:customer, tag_list: tag_list) }
let!(:tag_rule) { create(:tag_rule, enterprise: customer.enterprise, preferred_customer_tags: "two") }
it "serializes a customer with tags" do
tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: customer.enterprise_id))
- serializer = Api::Admin::CustomerSerializer.new customer, tag_rule_mapping: tag_rule_mapping
+ customer_tag_list = { customer.id => tag_list }
+ serializer = Api::Admin::CustomerSerializer.new customer,
+ tag_rule_mapping: tag_rule_mapping,
+ customer_tags: customer_tag_list
result = JSON.parse(serializer.to_json)
expect(result['email']).to eq customer.email
tags = result['tags']
@@ -27,4 +31,11 @@ describe Api::Admin::CustomerSerializer do
expect(tag['rules']).to be nil
end
end
+
+ it 'serializes a customer without customer_tags' do
+ serializer = Api::Admin::CustomerSerializer.new customer
+ result = JSON.parse(serializer.to_json)
+
+ expect(result['tags'].first['text']).to eq tag_list.first
+ end
end
diff --git a/spec/serializers/api/cached_enterprise_serializer_spec.rb b/spec/serializers/api/cached_enterprise_serializer_spec.rb
index c4e5624fa8..6bcaeffdc3 100644
--- a/spec/serializers/api/cached_enterprise_serializer_spec.rb
+++ b/spec/serializers/api/cached_enterprise_serializer_spec.rb
@@ -53,17 +53,9 @@ describe Api::CachedEnterpriseSerializer do
instance_double(OpenFoodNetwork::EnterpriseInjectionData, active_distributor_ids: [])
end
- it 'does not duplicate properties' do
+ it 'does not serialize distributed properties' do
properties = cached_enterprise_serializer.distributed_properties
- expect(properties.map(&:presentation)).to eq([property.presentation])
- end
-
- it 'fetches producer properties' do
- distributed_producer_properties = cached_enterprise_serializer
- .distributed_producer_properties
-
- expect(distributed_producer_properties.map(&:presentation))
- .to eq(producer.producer_properties.map(&:property).map(&:presentation))
+ expect(properties).to eq []
end
end
diff --git a/spec/services/order_cycle_form_spec.rb b/spec/services/order_cycle_form_spec.rb
index f264592763..a085961e26 100644
--- a/spec/services/order_cycle_form_spec.rb
+++ b/spec/services/order_cycle_form_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+require 'order_management/subscriptions/proxy_order_syncer'
describe OrderCycleForm do
describe "save" do
@@ -68,10 +69,10 @@ describe OrderCycleForm do
context "where I manage the order_cycle's coordinator" do
let(:form) { OrderCycleForm.new(coordinated_order_cycle, params, user) }
- let(:syncer_mock) { instance_double(OpenFoodNetwork::ProxyOrderSyncer, sync!: true) }
+ let(:syncer_mock) { instance_double(OrderManagement::Subscriptions::ProxyOrderSyncer, sync!: true) }
before do
- allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock }
+ allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock }
end
context "and I add an schedule that I own, and remove another that I own" do
diff --git a/spec/services/order_payment_finder_spec.rb b/spec/services/order_payment_finder_spec.rb
new file mode 100644
index 0000000000..3d71d9a706
--- /dev/null
+++ b/spec/services/order_payment_finder_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe OrderPaymentFinder do
+ let(:order) { create(:order_with_distributor) }
+ let(:finder) { OrderPaymentFinder.new(order) }
+
+ context "when order has several non pending payments" do
+ let!(:failed_payment) { create(:payment, order: order, state: 'failed') }
+ let!(:complete_payment) { create(:payment, order: order, state: 'completed') }
+
+ it "#last_payment returns the last payment" do
+ expect(finder.last_payment).to eq complete_payment
+ end
+
+ it "#last_pending_payment returns nil" do
+ expect(finder.last_pending_payment).to be nil
+ end
+ end
+
+ context "when order has a pending payment and a non pending payment" do
+ let!(:processing_payment) { create(:payment, order: order, state: 'processing') }
+ let!(:failed_payment) { create(:payment, order: order, state: 'failed') }
+
+ it "#last_payment returns the last payment" do
+ expect(finder.last_payment).to eq failed_payment
+ end
+
+ it "#last_pending_payment returns the pending payment" do
+ # a payment in the processing state is a pending payment
+ expect(finder.last_pending_payment).to eq processing_payment
+ end
+
+ context "and an extra last pending payment" do
+ let!(:pending_payment) { create(:payment, order: order, state: 'pending') }
+
+ it "#last_payment returns the last payment" do
+ expect(finder.last_payment).to eq pending_payment
+ end
+
+ it "#last_pending_payment returns the pending payment" do
+ expect(finder.last_pending_payment).to eq pending_payment
+ end
+ end
+ end
+end
diff --git a/spec/services/permissions/order_spec.rb b/spec/services/permissions/order_spec.rb
index d60d6968e2..88e3666aca 100644
--- a/spec/services/permissions/order_spec.rb
+++ b/spec/services/permissions/order_spec.rb
@@ -47,6 +47,18 @@ module Permissions
it "should let me see the order" do
expect(permissions.visible_orders).to include order
end
+
+ context "with search params" do
+ let(:search_params) { { completed_at_gt: Time.zone.now.yesterday.strftime('%Y-%m-%d') } }
+ let(:permissions) { Permissions::Order.new(user, search_params) }
+
+ it "only returns completed, non-cancelled orders within search filter range" do
+ expect(permissions.visible_orders).to include order_completed
+ expect(permissions.visible_orders).to_not include order_cancelled
+ expect(permissions.visible_orders).to_not include order_cart
+ expect(permissions.visible_orders).to_not include order_from_last_year
+ end
+ end
end
context "as a producer which has granted P-OC to the distributor of an order" do
@@ -71,18 +83,6 @@ module Permissions
expect(permissions.visible_orders).to_not include order
end
end
-
- context "with search params" do
- let(:search_params) { { completed_at_gt: Time.zone.now.yesterday.strftime('%Y-%m-%d') } }
- let(:permissions) { Permissions::Order.new(user, search_params) }
-
- it "only returns completed, non-cancelled orders within search filter range" do
- expect(permissions.visible_orders).to include order_completed
- expect(permissions.visible_orders).to_not include order_cancelled
- expect(permissions.visible_orders).to_not include order_cart
- expect(permissions.visible_orders).to_not include order_from_last_year
- end
- end
end
context "as an enterprise that is a distributor in the order cycle, but not the distributor of the order" do
diff --git a/spec/services/subscription_estimator_spec.rb b/spec/services/subscription_estimator_spec.rb
deleted file mode 100644
index 5230057888..0000000000
--- a/spec/services/subscription_estimator_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-describe SubscriptionEstimator do
- describe "estimating prices for subscription line items" do
- let!(:subscription) { create(:subscription, with_items: true) }
- let!(:sli1) { subscription.subscription_line_items.first }
- let!(:sli2) { subscription.subscription_line_items.second }
- let!(:sli3) { subscription.subscription_line_items.third }
- let(:estimator) { SubscriptionEstimator.new(subscription) }
-
- before do
- sli1.update_attributes(price_estimate: 4.0)
- sli2.update_attributes(price_estimate: 5.0)
- sli3.update_attributes(price_estimate: 6.0)
- sli1.variant.update_attributes(price: 1.0)
- sli2.variant.update_attributes(price: 2.0)
- sli3.variant.update_attributes(price: 3.0)
-
- # Simulating assignment of attrs from params
- sli1.assign_attributes(price_estimate: 7.0)
- sli2.assign_attributes(price_estimate: 8.0)
- sli3.assign_attributes(price_estimate: 9.0)
- end
-
- context "when a insufficient information exists to calculate price estimates" do
- before do
- # This might be because a shop has not been assigned yet, or no
- # current or future order cycles exist for the schedule
- allow(estimator).to receive(:fee_calculator) { nil }
- end
-
- it "resets the price estimates for all items" do
- estimator.estimate!
- expect(sli1.price_estimate).to eq 4.0
- expect(sli2.price_estimate).to eq 5.0
- expect(sli3.price_estimate).to eq 6.0
- end
- end
-
- context "when sufficient information to calculate price estimates exists" do
- let(:fee_calculator) { instance_double(OpenFoodNetwork::EnterpriseFeeCalculator) }
-
- before do
- allow(estimator).to receive(:fee_calculator) { fee_calculator }
- allow(fee_calculator).to receive(:indexed_fees_for).with(sli1.variant) { 1.0 }
- allow(fee_calculator).to receive(:indexed_fees_for).with(sli2.variant) { 0.0 }
- allow(fee_calculator).to receive(:indexed_fees_for).with(sli3.variant) { 3.0 }
- end
-
- context "when no variant overrides apply" do
- it "recalculates price_estimates based on variant prices and associated fees" do
- estimator.estimate!
- expect(sli1.price_estimate).to eq 2.0
- expect(sli2.price_estimate).to eq 2.0
- expect(sli3.price_estimate).to eq 6.0
- end
- end
-
- context "when variant overrides apply" do
- let!(:override1) { create(:variant_override, hub: subscription.shop, variant: sli1.variant, price: 1.2) }
- let!(:override2) { create(:variant_override, hub: subscription.shop, variant: sli2.variant, price: 2.3) }
-
- it "recalculates price_estimates based on override prices and associated fees" do
- estimator.estimate!
- expect(sli1.price_estimate).to eq 2.2
- expect(sli2.price_estimate).to eq 2.3
- expect(sli3.price_estimate).to eq 6.0
- end
- end
- end
- end
-
- describe "updating estimates for shipping and payment fees" do
- let(:subscription) { create(:subscription, with_items: true, payment_method: payment_method, shipping_method: shipping_method) }
- let!(:sli1) { subscription.subscription_line_items.first }
- let!(:sli2) { subscription.subscription_line_items.second }
- let!(:sli3) { subscription.subscription_line_items.third }
- let(:estimator) { SubscriptionEstimator.new(subscription) }
-
- before do
- allow(estimator).to receive(:assign_price_estimates)
- sli1.update_attributes(price_estimate: 4.0)
- sli2.update_attributes(price_estimate: 5.0)
- sli3.update_attributes(price_estimate: 6.0)
- end
-
- context "using flat rate calculators" do
- let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 12.34)) }
- let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 9.12)) }
-
- it "calculates fees based on the rates provided" do
- estimator.estimate!
- expect(subscription.shipping_fee_estimate.to_f).to eq 12.34
- expect(subscription.payment_fee_estimate.to_f).to eq 9.12
- end
- end
-
- context "using flat percent item total calculators" do
- let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)) }
- let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 20)) }
-
- it "calculates fees based on the estimated item total and percentage provided" do
- estimator.estimate!
- expect(subscription.shipping_fee_estimate.to_f).to eq 1.5
- expect(subscription.payment_fee_estimate.to_f).to eq 3.0
- end
- end
-
- context "using flat percent per item calculators" do
- let(:shipping_method) { create(:shipping_method, calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 5)) }
- let(:payment_method) { create(:payment_method, calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 10)) }
-
- it "calculates fees based on the estimated item prices and percentage provided" do
- estimator.estimate!
- expect(subscription.shipping_fee_estimate.to_f).to eq 0.75
- expect(subscription.payment_fee_estimate.to_f).to eq 1.5
- end
- end
-
- context "using per item calculators" do
- let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::PerItem.new(preferred_amount: 1.2)) }
- let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::PerItem.new(preferred_amount: 0.3)) }
-
- it "calculates fees based on the number of items and rate provided" do
- estimator.estimate!
- expect(subscription.shipping_fee_estimate.to_f).to eq 3.6
- expect(subscription.payment_fee_estimate.to_f).to eq 0.9
- end
- end
- end
-end
diff --git a/spec/services/subscription_form_spec.rb b/spec/services/subscription_form_spec.rb
deleted file mode 100644
index ae27363c8a..0000000000
--- a/spec/services/subscription_form_spec.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-require 'spec_helper'
-
-describe SubscriptionForm do
- describe "creating a new subscription" do
- let!(:shop) { create(:distributor_enterprise) }
- let!(:customer) { create(:customer, enterprise: shop) }
- let!(:product1) { create(:product, supplier: shop) }
- let!(:product2) { create(:product, supplier: shop) }
- let!(:product3) { create(:product, supplier: shop) }
- let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
- let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
- let!(:variant3) { create(:variant, product: product2, unit_value: '1000', price: 2.50, option_values: [], on_hand: 1) }
- let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
- let!(:order_cycle1) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 9.days.ago, orders_close_at: 2.days.ago) }
- let!(:order_cycle2) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.ago, orders_close_at: 5.days.from_now) }
- let!(:order_cycle3) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 5.days.from_now, orders_close_at: 12.days.from_now) }
- let!(:order_cycle4) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 12.days.from_now, orders_close_at: 19.days.from_now) }
- let!(:outgoing_exchange1) { order_cycle1.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) }
- let!(:outgoing_exchange2) { order_cycle2.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) }
- let!(:outgoing_exchange3) { order_cycle3.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant3], enterprise_fees: []) }
- let!(:outgoing_exchange4) { order_cycle4.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) }
- let!(:schedule) { create(:schedule, order_cycles: [order_cycle1, order_cycle2, order_cycle3, order_cycle4]) }
- let!(:payment_method) { create(:payment_method, distributors: [shop]) }
- let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
- let!(:address) { create(:address) }
- let(:subscription) { Subscription.new }
-
- let!(:params) {
- {
- shop_id: shop.id,
- customer_id: customer.id,
- schedule_id: schedule.id,
- bill_address_attributes: address.clone.attributes,
- ship_address_attributes: address.clone.attributes,
- payment_method_id: payment_method.id,
- shipping_method_id: shipping_method.id,
- begins_at: 4.days.ago,
- ends_at: 14.days.from_now,
- subscription_line_items_attributes: [
- { variant_id: variant1.id, quantity: 1, price_estimate: 7.0 },
- { variant_id: variant2.id, quantity: 2, price_estimate: 8.0 },
- { variant_id: variant3.id, quantity: 3, price_estimate: 9.0 }
- ]
- }
- }
-
- let(:form) { SubscriptionForm.new(subscription, params) }
-
- it "creates orders for each order cycle in the schedule" do
- expect(form.save).to be true
-
- expect(subscription.proxy_orders.count).to be 2
- expect(subscription.subscription_line_items.count).to be 3
- expect(subscription.subscription_line_items[0].price_estimate).to eq 13.75
- expect(subscription.subscription_line_items[1].price_estimate).to eq 7.75
- expect(subscription.subscription_line_items[2].price_estimate).to eq 4.25
-
- # This order cycle has already closed, so no order is initialized
- proxy_order1 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle1.id)
- expect(proxy_order1).to be nil
-
- # Currently open order cycle, closing after begins_at and before ends_at
- proxy_order2 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle2.id)
- expect(proxy_order2).to be_a ProxyOrder
- order2 = proxy_order2.initialise_order!
- expect(order2.line_items.count).to eq 3
- expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3
- expect(order2.shipments.count).to eq 1
- expect(order2.shipments.first.shipping_method).to eq shipping_method
- expect(order2.payments.count).to eq 1
- expect(order2.payments.first.payment_method).to eq payment_method
- expect(order2.payments.first.state).to eq 'checkout'
- expect(order2.total).to eq 42
- expect(order2.completed?).to be false
-
- # Future order cycle, closing after begins_at and before ends_at
- # Adds line items for variants that aren't yet available from the order cycle
- proxy_order3 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle3.id)
- expect(proxy_order3).to be_a ProxyOrder
- order3 = proxy_order3.initialise_order!
- expect(order3).to be_a Spree::Order
- expect(order3.line_items.count).to eq 3
- expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3
- expect(order3.shipments.count).to eq 1
- expect(order3.shipments.first.shipping_method).to eq shipping_method
- expect(order3.payments.count).to eq 1
- expect(order3.payments.first.payment_method).to eq payment_method
- expect(order3.payments.first.state).to eq 'checkout'
- expect(order3.total).to eq 31.50
- expect(order3.completed?).to be false
-
- # Future order cycle closing after ends_at
- proxy_order4 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle4.id)
- expect(proxy_order4).to be nil
- end
- end
-end
diff --git a/spec/services/subscription_validator_spec.rb b/spec/services/subscription_validator_spec.rb
deleted file mode 100644
index bdcd14bea5..0000000000
--- a/spec/services/subscription_validator_spec.rb
+++ /dev/null
@@ -1,470 +0,0 @@
-require "spec_helper"
-
-describe SubscriptionValidator do
- let(:owner) { create(:user) }
- let(:shop) { create(:enterprise, name: "Shop", owner: owner) }
-
- describe "delegation" do
- let(:subscription) { create(:subscription, shop: shop) }
- let(:validator) { SubscriptionValidator.new(subscription) }
-
- it "delegates to subscription" do
- expect(validator.shop).to eq subscription.shop
- expect(validator.customer).to eq subscription.customer
- expect(validator.schedule).to eq subscription.schedule
- expect(validator.shipping_method).to eq subscription.shipping_method
- expect(validator.payment_method).to eq subscription.payment_method
- expect(validator.bill_address).to eq subscription.bill_address
- expect(validator.ship_address).to eq subscription.ship_address
- expect(validator.begins_at).to eq subscription.begins_at
- expect(validator.ends_at).to eq subscription.ends_at
- end
- end
-
- describe "validations" do
- let(:subscription_stubs) do
- {
- shop: shop,
- customer: true,
- schedule: true,
- shipping_method: true,
- payment_method: true,
- bill_address: true,
- ship_address: true,
- begins_at: true,
- ends_at: true,
- }
- end
-
- let(:validation_stubs) do
- {
- shipping_method_allowed?: true,
- payment_method_allowed?: true,
- payment_method_type_allowed?: true,
- ends_at_after_begins_at?: true,
- customer_allowed?: true,
- schedule_allowed?: true,
- credit_card_ok?: true,
- subscription_line_items_present?: true,
- requested_variants_available?: true
- }
- end
-
- let(:subscription) { instance_double(Subscription, subscription_stubs) }
- let(:validator) { SubscriptionValidator.new(subscription) }
-
- def stub_validations(validator, methods)
- methods.each do |name, value|
- allow(validator).to receive(name) { value }
- end
- end
-
- describe "shipping method validation" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:shipping_method)) }
- before { stub_validations(validator, validation_stubs.except(:shipping_method_allowed?)) }
-
- context "when no shipping method is present" do
- before { expect(subscription).to receive(:shipping_method).at_least(:once) { nil } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:shipping_method]).to_not be_empty
- end
- end
-
- context "when a shipping method is present" do
- let(:shipping_method) { instance_double(Spree::ShippingMethod, distributors: [shop]) }
- before { expect(subscription).to receive(:shipping_method).at_least(:once) { shipping_method } }
-
- context "and the shipping method is not associated with the shop" do
- before { allow(shipping_method).to receive(:distributors) { [double(:enterprise)] } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:shipping_method]).to_not be_empty
- end
- end
-
- context "and the shipping method is associated with the shop" do
- before { allow(shipping_method).to receive(:distributors) { [shop] } }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:shipping_method]).to be_empty
- end
- end
- end
- end
-
- describe "payment method validation" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) }
- before { stub_validations(validator, validation_stubs.except(:payment_method_allowed?)) }
-
- context "when no payment method is present" do
- before { expect(subscription).to receive(:payment_method).at_least(:once) { nil } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "when a payment method is present" do
- let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) }
- before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } }
-
- context "and the payment method is not associated with the shop" do
- before { allow(payment_method).to receive(:distributors) { [double(:enterprise)] } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "and the payment method is associated with the shop" do
- before { allow(payment_method).to receive(:distributors) { [shop] } }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:payment_method]).to be_empty
- end
- end
- end
- end
-
- describe "payment method type validation" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) }
- before { stub_validations(validator, validation_stubs.except(:payment_method_type_allowed?)) }
-
- context "when a payment method is present" do
- let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) }
- before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } }
-
- context "and the payment method type is not in the approved list" do
- before { allow(payment_method).to receive(:type) { "Blah" } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "and the payment method is in the approved list" do
- let(:approved_type) { Subscription::ALLOWED_PAYMENT_METHOD_TYPES.first }
- before { allow(payment_method).to receive(:type) { approved_type } }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:payment_method]).to be_empty
- end
- end
- end
- end
-
- describe "dates" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:begins_at, :ends_at)) }
- before { stub_validations(validator, validation_stubs.except(:ends_at_after_begins_at?)) }
- before { expect(subscription).to receive(:begins_at).at_least(:once) { begins_at } }
-
- context "when no begins_at is present" do
- let(:begins_at) { nil }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:begins_at]).to_not be_empty
- end
- end
-
- context "when a start date is present" do
- let(:begins_at) { Time.zone.today }
- before { expect(subscription).to receive(:ends_at).at_least(:once) { ends_at } }
-
- context "when no ends_at is present" do
- let(:ends_at) { nil }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:ends_at]).to be_empty
- end
- end
-
- context "when ends_at is equal to begins_at" do
- let(:ends_at) { Time.zone.today }
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:ends_at]).to_not be_empty
- end
- end
-
- context "when ends_at is before begins_at" do
- let(:ends_at) { Time.zone.today - 1.day }
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:ends_at]).to_not be_empty
- end
- end
-
- context "when ends_at is after begins_at" do
- let(:ends_at) { Time.zone.today + 1.day }
- it "adds an error and returns false" do
- expect(validator.valid?).to be true
- expect(validator.errors[:ends_at]).to be_empty
- end
- end
- end
- end
-
- describe "addresses" do
- before { stub_validations(validator, validation_stubs) }
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:bill_address, :ship_address)) }
- before { expect(subscription).to receive(:bill_address).at_least(:once) { bill_address } }
- before { expect(subscription).to receive(:ship_address).at_least(:once) { ship_address } }
-
- context "when bill_address and ship_address are not present" do
- let(:bill_address) { nil }
- let(:ship_address) { nil }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:bill_address]).to_not be_empty
- expect(validator.errors[:ship_address]).to_not be_empty
- end
- end
-
- context "when bill_address and ship_address are present" do
- let(:bill_address) { instance_double(Spree::Address) }
- let(:ship_address) { instance_double(Spree::Address) }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:bill_address]).to be_empty
- expect(validator.errors[:ship_address]).to be_empty
- end
- end
- end
-
- describe "customer" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:customer)) }
- before { stub_validations(validator, validation_stubs.except(:customer_allowed?)) }
- before { expect(subscription).to receive(:customer).at_least(:once) { customer } }
-
- context "when no customer is present" do
- let(:customer) { nil }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:customer]).to_not be_empty
- end
- end
-
- context "when a customer is present" do
- let(:customer) { instance_double(Customer) }
-
- context "and the customer is not associated with the shop" do
- before { allow(customer).to receive(:enterprise) { double(:enterprise) } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:customer]).to_not be_empty
- end
- end
-
- context "and the customer is associated with the shop" do
- before { allow(customer).to receive(:enterprise) { shop } }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:customer]).to be_empty
- end
- end
- end
- end
-
- describe "schedule" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:schedule)) }
- before { stub_validations(validator, validation_stubs.except(:schedule_allowed?)) }
- before { expect(subscription).to receive(:schedule).at_least(:once) { schedule } }
-
- context "when no schedule is present" do
- let(:schedule) { nil }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:schedule]).to_not be_empty
- end
- end
-
- context "when a schedule is present" do
- let(:schedule) { instance_double(Schedule) }
-
- context "and the schedule is not associated with the shop" do
- before { allow(schedule).to receive(:coordinators) { [double(:enterprise)] } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:schedule]).to_not be_empty
- end
- end
-
- context "and the schedule is associated with the shop" do
- before { allow(schedule).to receive(:coordinators) { [shop] } }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:schedule]).to be_empty
- end
- end
- end
- end
-
- describe "credit card" do
- let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) }
- before { stub_validations(validator, validation_stubs.except(:credit_card_ok?)) }
- before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } }
-
- context "when using a Check payment method" do
- let(:payment_method) { instance_double(Spree::PaymentMethod, type: "Spree::PaymentMethod::Check") }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:subscription_line_items]).to be_empty
- end
- end
-
- context "when using the StripeConnect payment gateway" do
- let(:payment_method) { instance_double(Spree::PaymentMethod, type: "Spree::Gateway::StripeConnect") }
- before { expect(subscription).to receive(:customer).at_least(:once) { customer } }
-
- context "when the customer does not allow charges" do
- let(:customer) { instance_double(Customer, allow_charges: false) }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "when the customer allows charges" do
- let(:customer) { instance_double(Customer, allow_charges: true) }
-
- context "and the customer is not associated with a user" do
- before { allow(customer).to receive(:user) { nil } }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "and the customer is associated with a user" do
- before { expect(customer).to receive(:user).once { user } }
-
- context "and the user has no default card set" do
- let(:user) { instance_double(Spree::User, default_card: nil) }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:payment_method]).to_not be_empty
- end
- end
-
- context "and the user has a default card set" do
- let(:user) { instance_double(Spree::User, default_card: 'some card') }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:payment_method]).to be_empty
- end
- end
- end
- end
- end
- end
-
- describe "subscription line items" do
- let(:subscription) { instance_double(Subscription, subscription_stubs) }
- before { stub_validations(validator, validation_stubs.except(:subscription_line_items_present?)) }
- before { expect(subscription).to receive(:subscription_line_items).at_least(:once) { subscription_line_items } }
-
- context "when no subscription line items are present" do
- let(:subscription_line_items) { [] }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:subscription_line_items]).to_not be_empty
- end
- end
-
- context "when subscription line items are present but they are all marked for destruction" do
- let(:subscription_line_item1) { instance_double(SubscriptionLineItem, marked_for_destruction?: true) }
- let(:subscription_line_items) { [subscription_line_item1] }
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:subscription_line_items]).to_not be_empty
- end
- end
-
- context "when subscription line items are present and some and not marked for destruction" do
- let(:subscription_line_item1) { instance_double(SubscriptionLineItem, marked_for_destruction?: true) }
- let(:subscription_line_item2) { instance_double(SubscriptionLineItem, marked_for_destruction?: false) }
- let(:subscription_line_items) { [subscription_line_item1, subscription_line_item2] }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:subscription_line_items]).to be_empty
- end
- end
- end
-
- describe "variant availability" do
- let(:subscription) { instance_double(Subscription, subscription_stubs) }
- before { stub_validations(validator, validation_stubs.except(:requested_variants_available?)) }
- before { expect(subscription).to receive(:subscription_line_items).at_least(:once) { subscription_line_items } }
-
- context "when no subscription line items are present" do
- let(:subscription_line_items) { [] }
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:subscription_line_items]).to be_empty
- end
- end
-
- context "when subscription line items are present" do
- let(:variant1) { instance_double(Spree::Variant, id: 1) }
- let(:variant2) { instance_double(Spree::Variant, id: 2) }
- let(:subscription_line_item1) { instance_double(SubscriptionLineItem, variant: variant1) }
- let(:subscription_line_item2) { instance_double(SubscriptionLineItem, variant: variant2) }
- let(:subscription_line_items) { [subscription_line_item1] }
-
- context "but some variants are unavailable" do
- let(:product) { instance_double(Spree::Product, name: "some_name") }
-
- before do
- allow(validator).to receive(:available_variant_ids) { [variant2.id] }
- allow(variant1).to receive(:product) { product }
- allow(variant1).to receive(:full_name) { "some name" }
- end
-
- it "adds an error and returns false" do
- expect(validator.valid?).to be false
- expect(validator.errors[:subscription_line_items]).to_not be_empty
- end
- end
-
- context "and all requested variants are available" do
- before do
- allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] }
- end
-
- it "returns true" do
- expect(validator.valid?).to be true
- expect(validator.errors[:subscription_line_items]).to be_empty
- end
- end
- end
- end
- end
-end
diff --git a/spec/services/subscription_variants_service_spec.rb b/spec/services/subscription_variants_service_spec.rb
deleted file mode 100644
index 31d0ff4ca7..0000000000
--- a/spec/services/subscription_variants_service_spec.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-require "spec_helper"
-
-describe SubscriptionVariantsService do
- describe "variant eligibility for subscription" do
- let!(:shop) { create(:distributor_enterprise) }
- let!(:producer) { create(:supplier_enterprise) }
- let!(:product) { create(:product, supplier: producer) }
- let!(:variant) { product.variants.first }
-
- let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
- let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) }
- let!(:subscription_line_item) do
- create(:subscription_line_item, subscription: subscription, variant: variant)
- end
-
- let(:current_order_cycle) do
- create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago,
- orders_close_at: 1.week.from_now)
- end
-
- let(:future_order_cycle) do
- create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now,
- orders_close_at: 2.weeks.from_now)
- end
-
- let(:past_order_cycle) do
- create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago,
- orders_close_at: 1.week.ago)
- end
-
- let!(:order_cycle) { current_order_cycle }
-
- context "if the shop is the supplier for the product" do
- let!(:producer) { shop }
-
- it "is eligible" do
- expect(described_class.eligible_variants(shop)).to include(variant)
- end
- end
-
- context "if the supplier is permitted for the shop" do
- let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, parent: product.supplier, permissions_list: [:add_to_order_cycle]) }
-
- it "is eligible" do
- expect(described_class.eligible_variants(shop)).to include(variant)
- end
- end
-
- context "if the variant is involved in an exchange" do
- let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
- let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
-
- context "if it is an incoming exchange where the shop is the receiver" do
- let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
-
- it "is not eligible" do
- expect(described_class.eligible_variants(shop)).to_not include(variant)
- end
- end
-
- context "if it is an outgoing exchange where the shop is the receiver" do
- let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
-
- context "if the order cycle is currently open" do
- let!(:order_cycle) { current_order_cycle }
-
- it "is eligible" do
- expect(described_class.eligible_variants(shop)).to include(variant)
- end
- end
-
- context "if the order cycle opens in the future" do
- let!(:order_cycle) { future_order_cycle }
-
- it "is eligible" do
- expect(described_class.eligible_variants(shop)).to include(variant)
- end
- end
-
- context "if the order cycle closed in the past" do
- let!(:order_cycle) { past_order_cycle }
-
- it "is eligible" do
- expect(described_class.eligible_variants(shop)).to include(variant)
- end
- end
- end
- end
-
- context "if the variant is unrelated" do
- it "is not eligible" do
- expect(described_class.eligible_variants(shop)).to_not include(variant)
- end
- end
- end
-
- describe "checking if variant in open and upcoming order cycles" do
- let!(:shop) { create(:enterprise) }
- let!(:product) { create(:product) }
- let!(:variant) { product.variants.first }
- let!(:schedule) { create(:schedule) }
-
- context "if the variant is involved in an exchange" do
- let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
- let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
-
- context "if it is an incoming exchange where the shop is the receiver" do
- let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
-
- it "is is false" do
- expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
- end
- end
-
- context "if it is an outgoing exchange where the shop is the receiver" do
- let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
-
- it "is true" do
- expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
- end
- end
- end
-
- context "if the variant is unrelated" do
- it "is false" do
- expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
- end
- end
- end
-end
diff --git a/spec/services/subscriptions_count_spec.rb b/spec/services/subscriptions_count_spec.rb
deleted file mode 100644
index 2446bcc8bf..0000000000
--- a/spec/services/subscriptions_count_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-describe SubscriptionsCount do
- let(:oc1) { create(:simple_order_cycle) }
- let(:oc2) { create(:simple_order_cycle) }
- let(:subscriptions_count) { SubscriptionsCount.new(order_cycles) }
-
- describe "#for" do
- context "when the collection has not been set" do
- let(:order_cycles) { nil }
- it "returns 0" do
- expect(subscriptions_count.for(oc1.id)).to eq 0
- end
- end
-
- context "when the collection has been set" do
- let(:order_cycles) { OrderCycle.where(id: [oc1]) }
- let!(:po1) { create(:proxy_order, order_cycle: oc1) }
- let!(:po2) { create(:proxy_order, order_cycle: oc1) }
- let!(:po3) { create(:proxy_order, order_cycle: oc2) }
-
- context "but the requested id is not present in the list of order cycles provided" do
- it "returns 0" do
- # Note that po3 applies to oc2, but oc2 in not in the collection
- expect(subscriptions_count.for(oc2.id)).to eq 0
- end
- end
-
- context "and the requested id is present in the list of order cycles provided" do
- it "returns a count of active proxy orders associated with the requested order cycle" do
- expect(subscriptions_count.for(oc1.id)).to eq 2
- end
- end
- end
- end
-end
diff --git a/spec/services/variant_overrides_indexed_spec.rb b/spec/services/variant_overrides_indexed_spec.rb
new file mode 100644
index 0000000000..15af405683
--- /dev/null
+++ b/spec/services/variant_overrides_indexed_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe VariantOverridesIndexed do
+ subject(:variant_overrides) { described_class.new([variant.id],[distributor.id]) }
+
+ let(:distributor) { create(:distributor_enterprise) }
+ let(:variant) { create(:variant) }
+ let!(:variant_override) do
+ create(
+ :variant_override,
+ hub: vo_distributor,
+ variant: vo_variant,
+ )
+ end
+
+ describe '#indexed' do
+ let(:result) { variant_overrides.indexed }
+
+ context 'when variant overrides exist for variants of specified variants' do
+ let(:vo_variant) { variant }
+
+ context 'when variant overrides apply to one of the specified distributors' do
+ let(:vo_distributor) { distributor }
+
+ it 'they are included in the mapping' do
+ expect(result).to eq(
+ distributor.id => { variant => variant_override }
+ )
+ end
+ end
+
+ context 'when variant overrides don\'t apply to one of the specified distributors' do
+ let(:vo_distributor) { create(:distributor_enterprise) }
+
+ it 'they are not included in the mapping' do
+ expect(result).to eq({})
+ end
+ end
+ end
+
+ context 'when variant overrides exist for other variants' do
+ let(:vo_variant) { create(:variant) }
+
+ context 'when variant overrides apply to one of the specified distributors' do
+ let(:vo_distributor) { distributor }
+
+ it 'they are not included in the mapping' do
+ expect(result).to eq({})
+ end
+ end
+
+ context 'when variant overrides don\'t apply to one of the specified distributors' do
+ let(:vo_distributor) { create(:distributor_enterprise) }
+
+ it 'they are not included in the mapping' do
+ expect(result).to eq({})
+ end
+ end
+ end
+ end
+end