diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index 352e5bf8cc..4a3e5bac81 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -10,6 +10,12 @@ Spree::Product.class_eval do validates_presence_of :supplier + validates_presence_of :variant_unit, if: :has_variants? + validates_presence_of :variant_unit_scale, + if: -> p { %w(weight volume).include? p.variant_unit } + validates_presence_of :variant_unit_name, + if: -> p { p.variant_unit == 'items' } + after_initialize :set_available_on_to_now, :if => :new_record? diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb new file mode 100644 index 0000000000..10fe4234db --- /dev/null +++ b/app/models/spree/variant_decorator.rb @@ -0,0 +1,7 @@ +Spree::Variant.class_eval do + validates_presence_of :unit_value, + if: -> v { %w(weight volume).include? v.product.variant_unit } + + validates_presence_of :unit_description, + if: -> v { v.product.variant_unit.present? && v.unit_value.nil? } +end diff --git a/db/migrate/20131128034556_setup_product_units_and_values.rb b/db/migrate/20131128034556_setup_product_units_and_values.rb new file mode 100644 index 0000000000..d6cf779aed --- /dev/null +++ b/db/migrate/20131128034556_setup_product_units_and_values.rb @@ -0,0 +1,14 @@ +class SetupProductUnitsAndValues < ActiveRecord::Migration + def change + change_table :spree_products do |t| + t.string :variant_unit + t.float :variant_unit_scale + t.string :variant_unit_name + end + + change_table :spree_variants do |t| + t.float :unit_value + t.string :unit_description + end + end +end diff --git a/db/schema.rb b/db/schema.rb index a95c7c04b5..5265be891e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20131030031125) do +ActiveRecord::Schema.define(:version => 20131128034556) do create_table "adjustment_metadata", :force => true do |t| t.integer "adjustment_id" @@ -481,9 +481,9 @@ ActiveRecord::Schema.define(:version => 20131030031125) do t.string "email" t.text "special_instructions" t.integer "distributor_id" - t.integer "order_cycle_id" t.string "currency" t.string "last_ip_address" + t.integer "order_cycle_id" t.integer "cart_id" end @@ -611,6 +611,9 @@ ActiveRecord::Schema.define(:version => 20131030031125) do t.boolean "group_buy" t.float "group_buy_unit_size" t.boolean "on_demand", :default => false + t.string "variant_unit" + t.float "variant_unit_scale" + t.string "variant_unit_name" end add_index "spree_products", ["available_on"], :name => "index_products_on_available_on" @@ -872,20 +875,22 @@ ActiveRecord::Schema.define(:version => 20131030031125) do add_index "spree_users", ["persistence_token"], :name => "index_users_on_persistence_token" create_table "spree_variants", :force => true do |t| - t.string "sku", :default => "", :null => false - t.decimal "weight", :precision => 8, :scale => 2 - t.decimal "height", :precision => 8, :scale => 2 - t.decimal "width", :precision => 8, :scale => 2 - t.decimal "depth", :precision => 8, :scale => 2 + t.string "sku", :default => "", :null => false + t.decimal "weight", :precision => 8, :scale => 2 + t.decimal "height", :precision => 8, :scale => 2 + t.decimal "width", :precision => 8, :scale => 2 + t.decimal "depth", :precision => 8, :scale => 2 t.datetime "deleted_at" - t.boolean "is_master", :default => false + t.boolean "is_master", :default => false t.integer "product_id" - t.integer "count_on_hand", :default => 0 - t.decimal "cost_price", :precision => 8, :scale => 2 + t.integer "count_on_hand", :default => 0 + t.decimal "cost_price", :precision => 8, :scale => 2 t.integer "position" - t.integer "lock_version", :default => 0 - t.boolean "on_demand", :default => false + t.integer "lock_version", :default => 0 + t.boolean "on_demand", :default => false t.string "cost_currency" + t.float "unit_value" + t.string "unit_description" end add_index "spree_variants", ["product_id"], :name => "index_variants_on_product_id" diff --git a/spec/factories.rb b/spec/factories.rb index 3791cd4143..f036156402 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -153,6 +153,15 @@ FactoryGirl.modify do supplier { Enterprise.is_primary_producer.first || FactoryGirl.create(:supplier_enterprise) } on_hand 3 + + variant_unit 'weight' + variant_unit_scale 1 + variant_unit_name '' + end + + factory :base_variant do + unit_value 1 + unit_description '' end factory :shipping_method do diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 7d4459b3b7..7fe3c4219a 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -14,7 +14,7 @@ module Spree end it "requires a supplier" do - product = create(:product) + product = create(:simple_product) product.supplier = nil product.should_not be_valid end @@ -24,6 +24,73 @@ module Spree product = Product.new product.available_on.should == Time.now end + + context "when the product has variants" do + let(:product) do + product = create(:simple_product) + create(:variant, product: product) + product + end + + it "requires a unit" do + product.variant_unit = nil + product.should_not be_valid + end + + %w(weight volume).each do |unit| + context "when unit is #{unit}" do + it "is valid when unit scale is set and unit name is not" do + product.variant_unit = unit + product.variant_unit_scale = 1 + product.variant_unit_name = nil + product.should be_valid + end + + it "is invalid when unit scale is not set" do + product.variant_unit = unit + product.variant_unit_scale = nil + product.variant_unit_name = nil + product.should_not be_valid + end + end + end + + context "when the unit is items" do + it "is valid when unit name is set and unit scale is not" do + product.variant_unit = 'items' + product.variant_unit_name = 'loaf' + product.variant_unit_scale = nil + product.should be_valid + end + + it "is invalid when unit name is not set" do + product.variant_unit = 'items' + product.variant_unit_name = nil + product.variant_unit_scale = nil + product.should_not be_valid + end + end + end + + context "when product does not have variants" do + let(:product) { create(:simple_product) } + + it "does not require any variant unit fields" do + product.variant_unit = nil + product.variant_unit_name = nil + product.variant_unit_scale = nil + + product.should be_valid + end + + it "requires a unit scale when variant unit is weight" do + product.variant_unit = 'weight' + product.variant_unit_scale = nil + product.variant_unit_name = nil + + product.should_not be_valid + end + end end diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb new file mode 100644 index 0000000000..0baf0b53bc --- /dev/null +++ b/spec/models/spree/variant_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper' + +module Spree + describe Variant do + context "when the product has variants" do + let!(:product) { create(:simple_product) } + let!(:variant) { create(:variant, product: product) } + + %w(weight volume).each do |unit| + context "when the product's unit is #{unit}" do + before do + product.update_attribute :variant_unit, unit + end + + it "is valid when unit value is set and unit description is not" do + variant.unit_value = 1 + variant.unit_description = nil + variant.should be_valid + end + + it "is invalid when unit value is not set" do + variant.unit_value = nil + variant.should_not be_valid + end + end + end + + context "when the product's unit is items" do + before do + product.update_attribute :variant_unit, 'items' + end + + it "is valid with only unit value set" do + variant.unit_value = 1 + variant.unit_description = nil + variant.should be_valid + end + + it "is valid with only unit description set" do + variant.unit_value = nil + variant.unit_description = 'Medium' + variant.should be_valid + end + + it "is invalid when neither unit value nor unit description are set" do + variant.unit_value = nil + variant.unit_description = nil + variant.should_not be_valid + end + end + end + + context "when the product does not have variants" do + let(:product) { create(:simple_product, variant_unit: nil) } + let(:variant) { product.master } + + it "does not require unit value or unit description when the product's unit is empty" do + variant.unit_value = nil + variant.unit_description = nil + variant.should be_valid + end + end + end +end