spree_core 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/logo/spree_50.png +0 -0
  3. data/app/assets/images/noimage/large.png +0 -0
  4. data/app/assets/images/noimage/mini.png +0 -0
  5. data/app/assets/images/noimage/product.png +0 -0
  6. data/app/assets/images/noimage/small.png +0 -0
  7. data/app/controllers/spree/base_controller.rb +3 -0
  8. data/app/helpers/spree/base_helper.rb +15 -11
  9. data/app/models/spree/adjustment.rb +5 -0
  10. data/app/models/spree/app_configuration.rb +3 -3
  11. data/app/models/spree/calculator/default_tax.rb +2 -2
  12. data/app/models/spree/calculator/percent_per_item.rb +9 -5
  13. data/app/models/spree/calculator.rb +1 -1
  14. data/app/models/spree/credit_card.rb +25 -0
  15. data/app/models/spree/line_item.rb +9 -0
  16. data/app/models/spree/new_adjustment.rb +4 -0
  17. data/app/models/spree/order/checkout.rb +4 -5
  18. data/app/models/spree/order.rb +52 -25
  19. data/app/models/spree/order_contents.rb +8 -7
  20. data/app/models/spree/order_inventory.rb +13 -13
  21. data/app/models/spree/order_populator.rb +4 -14
  22. data/app/models/spree/order_updater.rb +1 -1
  23. data/app/models/spree/payment/processing.rb +5 -0
  24. data/app/models/spree/payment.rb +12 -1
  25. data/app/models/spree/payment_method.rb +1 -4
  26. data/app/models/spree/product.rb +44 -17
  27. data/app/models/spree/promotion/actions/create_adjustment.rb +1 -1
  28. data/app/models/spree/promotion/actions/create_line_items.rb +32 -2
  29. data/app/models/spree/promotion.rb +2 -1
  30. data/app/models/spree/shipment.rb +5 -5
  31. data/app/models/spree/shipping_adjustment.rb +4 -0
  32. data/app/models/spree/shipping_method.rb +6 -0
  33. data/app/models/spree/shipping_rate.rb +1 -0
  34. data/app/models/spree/stock/availability_validator.rb +5 -3
  35. data/app/models/spree/stock/coordinator.rb +16 -4
  36. data/app/models/spree/stock/estimator.rb +16 -6
  37. data/app/models/spree/stock/packer.rb +2 -1
  38. data/app/models/spree/stock_location.rb +16 -6
  39. data/app/models/spree/tax_category.rb +1 -7
  40. data/app/models/spree/tax_rate.rb +1 -0
  41. data/app/models/spree/variant.rb +16 -3
  42. data/app/models/spree/zone.rb +1 -1
  43. data/config/initializers/user_class_extensions.rb +1 -1
  44. data/config/locales/en.yml +15 -1
  45. data/db/migrate/20130228210442_create_shipping_method_zone.rb +6 -1
  46. data/db/migrate/20130306181701_add_address_fields_to_stock_location.rb +4 -1
  47. data/db/migrate/20130515180736_add_backorderable_default_to_spree_stock_location.rb +5 -0
  48. data/db/migrate/20130516151222_add_propage_all_variants_to_spree_stock_location.rb +5 -0
  49. data/db/migrate/20130626232741_add_cvv_result_code_and_cvv_result_message_to_spree_payments.rb +6 -0
  50. data/db/migrate/20130628021056_add_unique_index_to_permalink_on_spree_products.rb +5 -0
  51. data/db/migrate/20130628022817_add_unique_index_to_orders_shipments_and_stock_transfers.rb +7 -0
  52. data/db/migrate/20130708052307_add_deleted_at_to_spree_tax_rates.rb +5 -0
  53. data/db/migrate/20130711200933_remove_lock_version_from_inventory_units.rb +6 -0
  54. data/db/migrate/20130718042445_add_cost_price_to_line_item.rb +5 -0
  55. data/db/migrate/20130718233855_set_backorderable_to_default_to_false.rb +6 -0
  56. data/db/migrate/20130725031716_add_created_by_id_to_spree_orders.rb +5 -0
  57. data/db/migrate/20130729214043_index_completed_at_on_spree_orders.rb +5 -0
  58. data/db/migrate/20130802014537_add_tax_category_id_to_spree_line_items.rb +5 -0
  59. data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +9 -0
  60. data/db/migrate/20130805043440_create_spree_new_adjustments.rb +8 -0
  61. data/lib/generators/spree/dummy/templates/rails/database.yml +8 -7
  62. data/lib/generators/spree/install/install_generator.rb +1 -1
  63. data/lib/spree/core/calculated_adjustments.rb +12 -1
  64. data/lib/spree/core/controller_helpers/order.rb +5 -3
  65. data/lib/spree/core/controller_helpers/search.rb +14 -0
  66. data/lib/spree/core/permalinks.rb +13 -13
  67. data/lib/spree/core/s3_support.rb +1 -1
  68. data/lib/spree/core/version.rb +1 -1
  69. data/lib/spree/core.rb +7 -5
  70. data/lib/spree/i18n/base.rb +17 -0
  71. data/lib/spree/i18n/initializer.rb +1 -0
  72. data/lib/spree/i18n.rb +28 -7
  73. data/lib/spree/money.rb +2 -0
  74. data/lib/spree/testing_support/authorization_helpers.rb +6 -15
  75. data/lib/spree/testing_support/capybara_ext.rb +20 -11
  76. data/lib/spree/testing_support/common_rake.rb +13 -0
  77. data/lib/spree/testing_support/factories/country_factory.rb +1 -1
  78. data/lib/spree/testing_support/factories/order_factory.rb +0 -2
  79. data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -1
  80. data/lib/spree/testing_support/factories/product_factory.rb +8 -18
  81. data/lib/spree/testing_support/factories/return_authorization_factory.rb +4 -0
  82. data/lib/spree/testing_support/factories/shipment_factory.rb +1 -1
  83. data/lib/spree/testing_support/factories/stock_item_factory.rb +2 -1
  84. data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -2
  85. data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
  86. data/lib/spree/testing_support/order_walkthrough.rb +14 -1
  87. data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
  88. data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
  89. data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
  90. data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
  91. data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
  92. data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
  93. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
  94. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
  95. data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
  96. data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
  97. data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
  98. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
  99. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
  100. metadata +118 -67
@@ -20,6 +20,7 @@
20
20
 
21
21
  module Spree
22
22
  class Product < ActiveRecord::Base
23
+ acts_as_paranoid
23
24
  has_many :product_option_types, dependent: :destroy
24
25
  has_many :option_types, through: :product_option_types
25
26
  has_many :product_properties, dependent: :destroy
@@ -44,12 +45,11 @@ module Spree
44
45
 
45
46
  has_many :variants_including_master,
46
47
  class_name: 'Spree::Variant',
47
- conditions: { deleted_at: nil },
48
- dependent: :destroy
49
-
50
- has_many :variants_including_master_and_deleted, class_name: 'Spree::Variant'
48
+ dependent: :destroy,
49
+ order: "#{::Spree::Variant.quoted_table_name}.position ASC"
51
50
 
52
51
  has_many :prices, through: :variants, order: 'spree_variants.position, spree_variants.id, currency'
52
+ has_many :stock_items, through: :variants
53
53
 
54
54
  delegate_belongs_to :master, :sku, :price, :currency, :display_amount, :display_price, :weight, :height, :width, :depth, :is_master, :has_default_price?, :cost_currency, :price_in, :amount_in
55
55
  delegate_belongs_to :master, :cost_price if Variant.table_exists? && Variant.column_names.include?('cost_price')
@@ -66,16 +66,35 @@ module Spree
66
66
 
67
67
  accepts_nested_attributes_for :variants, allow_destroy: true
68
68
 
69
- validates :name, :permalink, presence: true
69
+ validates :name, presence: true
70
+ validates :permalink, presence: true
70
71
  validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
72
+ validates :shipping_category_id, presence: true
71
73
 
72
74
  attr_accessor :option_values_hash
73
75
 
74
- attr_accessible :name, :description, :available_on, :permalink, :meta_description,
75
- :meta_keywords, :price, :sku, :deleted_at, :prototype_id,
76
- :option_values_hash, :weight, :height, :width, :depth,
77
- :shipping_category_id, :tax_category_id, :product_properties_attributes,
78
- :variants_attributes, :taxon_ids, :option_type_ids, :cost_currency
76
+ attr_accessible :available_on,
77
+ :cost_currency,
78
+ :deleted_at,
79
+ :depth,
80
+ :description,
81
+ :height,
82
+ :meta_description,
83
+ :meta_keywords,
84
+ :name,
85
+ :option_type_ids,
86
+ :option_values_hash,
87
+ :permalink,
88
+ :price,
89
+ :product_properties_attributes,
90
+ :prototype_id,
91
+ :shipping_category_id,
92
+ :sku,
93
+ :tax_category_id,
94
+ :taxon_ids,
95
+ :weight,
96
+ :width,
97
+ :variants_attributes
79
98
 
80
99
  attr_accessible :cost_price if Variant.table_exists? && Variant.column_names.include?('cost_price')
81
100
 
@@ -109,13 +128,6 @@ module Spree
109
128
  end
110
129
  end
111
130
 
112
- # override the delete method to set deleted_at value
113
- # instead of actually deleting the product.
114
- def delete
115
- self.update_column(:deleted_at, Time.now)
116
- variants_including_master.update_all(deleted_at: Time.now)
117
- end
118
-
119
131
  # Adding properties and option types on creation based on a chosen prototype
120
132
  attr_reader :prototype_id
121
133
  def prototype_id=(value)
@@ -197,6 +209,21 @@ module Spree
197
209
  Spree::Promotion.advertised.where(id: promotion_ids).reject(&:expired?)
198
210
  end
199
211
 
212
+ def total_on_hand
213
+ if Spree::Config.track_inventory_levels
214
+ self.stock_items.sum(&:count_on_hand)
215
+ else
216
+ Float::INFINITY
217
+ end
218
+ end
219
+
220
+ # Master variant may be deleted (i.e. when the product is deleted)
221
+ # which would make AR's default finder return nil.
222
+ # This is a stopgap for that little problem.
223
+ def master
224
+ super || variants_including_master.with_deleted.where(:is_master => true).first
225
+ end
226
+
200
227
  private
201
228
 
202
229
  # Builds variants from a hash of option types & values
@@ -17,7 +17,7 @@ module Spree
17
17
  # through options hash
18
18
  def perform(options = {})
19
19
  order = options[:order]
20
- return if order.promotion_credit_exists?(self.promotion)
20
+ return if order.promotion_credit_exists?(self)
21
21
 
22
22
  self.create_adjustment("#{Spree.t(:promotion)} (#{promotion.name})", order, order)
23
23
  end
@@ -6,14 +6,44 @@ module Spree
6
6
  accepts_nested_attributes_for :promotion_action_line_items
7
7
  attr_accessible :promotion_action_line_items_attributes
8
8
 
9
+ delegate :eligible?, :to => :promotion
9
10
 
11
+ # Adds a line item to the Order if the promotion is eligible
12
+ #
13
+ # This doesn't play right with Add to Cart events because at the moment
14
+ # the item was added to cart the promo may not be eligible. However it
15
+ # might become eligible as the order gets updated.
16
+ #
17
+ # e.g.
18
+ # - A promo adds a line item to cart if order total greater then $30
19
+ # - Customer add 1 item of $10 to cart
20
+ # - This action shouldn't perform because the order is not eligible
21
+ # - Customer increases item quantity to 5 (order total goes to $50)
22
+ # - Now the order is eligible for the promo and the action should perform
23
+ #
24
+ # Another complication is when the same line item created by the promo
25
+ # is also added to cart on a separate action.
26
+ #
27
+ # e.g.
28
+ # - Promo adds 1 item A to cart if order total greater then $30
29
+ # - Customer add 2 items B to cart, current order total is $40
30
+ # - This action performs adding item A to cart since order is eligible
31
+ # - Customer changes his mind and updates item B quantity to 1
32
+ # - At this point order is no longer eligible and one might expect
33
+ # that item A should be removed
34
+ #
35
+ # It doesn't remove items from the order here because there's no way
36
+ # it can know whether that item was added via this promo action or if
37
+ # it was manually populated somewhere else. In that case the item
38
+ # needs to be manually removed from the order by the customer
10
39
  def perform(options = {})
11
- return unless order = options[:order]
40
+ order = options[:order]
41
+ return unless self.eligible? order
42
+
12
43
  promotion_action_line_items.each do |item|
13
44
  current_quantity = order.quantity_of(item.variant)
14
45
  if current_quantity < item.quantity
15
46
  order.contents.add(item.variant, item.quantity - current_quantity)
16
- order.update!
17
47
  end
18
48
  end
19
49
  end
@@ -44,9 +44,10 @@ module Spree
44
44
  def activate(payload)
45
45
  return unless order_activatable? payload[:order]
46
46
 
47
+ # make sure code is always downcased (old databases might have mixed case codes)
47
48
  if code.present?
48
49
  event_code = payload[:coupon_code]
49
- return unless event_code == self.code
50
+ return unless event_code == self.code.downcase.strip
50
51
  end
51
52
 
52
53
  if path.present?
@@ -6,7 +6,7 @@ module Spree
6
6
  belongs_to :address, class_name: 'Spree::Address'
7
7
  belongs_to :stock_location, class_name: 'Spree::StockLocation'
8
8
 
9
- has_many :shipping_rates
9
+ has_many :shipping_rates, dependent: :destroy
10
10
  has_many :shipping_methods, through: :shipping_rates
11
11
  has_many :state_changes, as: :stateful
12
12
  has_many :inventory_units, dependent: :destroy
@@ -16,7 +16,7 @@ module Spree
16
16
  after_save :ensure_correct_adjustment, :update_order
17
17
 
18
18
  attr_accessor :special_instructions
19
- attr_accessible :order, :special_instructions, :stock_location_id,
19
+ attr_accessible :order, :special_instructions, :stock_location_id, :number,
20
20
  :tracking, :address, :inventory_units, :selected_shipping_rate_id
21
21
 
22
22
  accepts_nested_attributes_for :address
@@ -158,7 +158,7 @@ module Spree
158
158
  end
159
159
 
160
160
  def manifest
161
- inventory_units.group_by(&:variant).map do |variant, units|
161
+ inventory_units.includes(:variant).group_by(&:variant).map do |variant, units|
162
162
  states = {}
163
163
  units.group_by(&:state).each { |state, iu| states[state] = iu.count }
164
164
  OpenStruct.new(variant: variant, quantity: units.length, states: states)
@@ -223,8 +223,8 @@ module Spree
223
223
 
224
224
  def to_package
225
225
  package = Stock::Package.new(stock_location, order)
226
- inventory_units.each do |inventory_unit|
227
- package.add inventory_unit.variant, 1, inventory_unit.state
226
+ inventory_units.includes(:variant).each do |inventory_unit|
227
+ package.add inventory_unit.variant, 1, inventory_unit.state_name
228
228
  end
229
229
  package
230
230
  end
@@ -0,0 +1,4 @@
1
+ module Spree
2
+ class ShippingAdjustment < Spree::Adjustment
3
+ end
4
+ end
@@ -8,6 +8,7 @@ module Spree
8
8
  has_many :shipments
9
9
  has_many :shipping_method_categories
10
10
  has_many :shipping_categories, through: :shipping_method_categories
11
+ has_many :shipping_rates
11
12
 
12
13
  has_and_belongs_to_many :zones, :join_table => 'spree_shipping_methods_zones',
13
14
  :class_name => 'Spree::Zone',
@@ -49,6 +50,11 @@ module Spree
49
50
  spree_calculators.send(model_name_without_spree_namespace).select{|c| c.name.start_with?("Spree::Calculator::Shipping::")}
50
51
  end
51
52
 
53
+ # Some shipping methods are only meant to be set via backend
54
+ def frontend?
55
+ self.display_on != "back_end"
56
+ end
57
+
52
58
  private
53
59
  def at_least_one_shipping_category
54
60
  if self.shipping_categories.empty?
@@ -21,5 +21,6 @@ module Spree
21
21
 
22
22
  Spree::Money.new(price, { currency: currency })
23
23
  end
24
+ alias_method :display_cost, :display_price
24
25
  end
25
26
  end
@@ -1,14 +1,16 @@
1
1
  module Spree
2
2
  module Stock
3
3
  class AvailabilityValidator < ActiveModel::Validator
4
-
5
4
  def validate(line_item)
6
5
  quantifier = Stock::Quantifier.new(line_item.variant_id)
7
6
 
8
7
  unless quantifier.can_supply? line_item.quantity
9
- line_item.errors[:quantity] << I18n.t('validation.exceeds_available_stock')
10
- end
8
+ variant = line_item.variant
9
+ display_name = %Q{#{variant.name}}
10
+ display_name += %Q{ (#{variant.options_text})} unless variant.options_text.blank?
11
11
 
12
+ line_item.errors[:quantity] << Spree.t(:out_of_stock, :scope => :order_populator, :item => display_name.inspect)
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -8,21 +8,33 @@ module Spree
8
8
  end
9
9
 
10
10
  def packages
11
- packages = Array.new
12
- packages = build_packages(packages)
11
+ packages = build_packages
13
12
  packages = prioritize_packages(packages)
14
13
  packages = estimate_packages(packages)
15
14
  end
16
15
 
17
- private
18
- def build_packages(packages)
16
+ # Build packages as per stock location
17
+ #
18
+ # It needs to check whether each stock location holds at least one stock
19
+ # item for the order. In case none is found it wouldn't make any sense
20
+ # to build a package because it would be empty. Plus we avoid errors down
21
+ # the stack because it would assume the stock location has stock items
22
+ # for the given order
23
+ #
24
+ # Returns an array of Package instances
25
+ def build_packages(packages = Array.new)
19
26
  StockLocation.active.each do |stock_location|
27
+ next unless order.line_items.any? do |item|
28
+ stock_location.stock_item(item.variant)
29
+ end
30
+
20
31
  packer = build_packer(stock_location, order)
21
32
  packages += packer.packages
22
33
  end
23
34
  packages
24
35
  end
25
36
 
37
+ private
26
38
  def prioritize_packages(packages)
27
39
  prioritizer = Prioritizer.new(order, packages)
28
40
  prioritizer.prioritized_packages
@@ -8,25 +8,35 @@ module Spree
8
8
  @currency = order.currency
9
9
  end
10
10
 
11
- def shipping_rates(package)
11
+ def shipping_rates(package, frontend_only = true)
12
12
  shipping_rates = Array.new
13
13
  shipping_methods = shipping_methods(package)
14
14
  return [] unless shipping_methods
15
+
15
16
  shipping_methods.each do |shipping_method|
16
17
  cost = calculate_cost(shipping_method, package)
17
-
18
- shipping_rates << ShippingRate.new( :shipping_method => shipping_method,
19
- :cost => cost)
18
+ shipping_rates << shipping_method.shipping_rates.new(:cost => cost)
20
19
  end
20
+
21
21
  shipping_rates.sort_by! { |r| r.cost || 0 }
22
- shipping_rates.first.selected = true unless shipping_rates.empty?
22
+
23
+ unless shipping_rates.empty?
24
+ if frontend_only
25
+ shipping_rates.each do |rate|
26
+ rate.selected = true and break if rate.shipping_method.frontend?
27
+ end
28
+ else
29
+ shipping_rates.first.selected = true
30
+ end
31
+ end
32
+
23
33
  shipping_rates
24
34
  end
25
35
 
26
36
  private
27
37
  def shipping_methods(package)
28
38
  shipping_methods = package.shipping_methods
29
- shipping_methods.delete_if { |ship_method| !ship_method.calculator.available?(package.contents) }
39
+ shipping_methods.delete_if { |ship_method| !ship_method.calculator.available?(package) }
30
40
  shipping_methods.delete_if { |ship_method| !ship_method.include?(order.ship_address) }
31
41
  shipping_methods.delete_if { |ship_method| !(ship_method.calculator.preferences[:currency].nil? || ship_method.calculator.preferences[:currency] == currency) }
32
42
  shipping_methods
@@ -16,6 +16,8 @@ module Spree
16
16
  def default_package
17
17
  package = Package.new(stock_location, order)
18
18
  order.line_items.each do |line_item|
19
+ next unless stock_location.stock_item(line_item.variant)
20
+
19
21
  on_hand, backordered = stock_location.fill_status(line_item.variant, line_item.quantity)
20
22
  package.add line_item.variant, on_hand, :on_hand if on_hand > 0
21
23
  package.add line_item.variant, backordered, :backordered if backordered > 0
@@ -34,4 +36,3 @@ module Spree
34
36
  end
35
37
  end
36
38
  end
37
-
@@ -9,11 +9,24 @@ module Spree
9
9
  validates_presence_of :name
10
10
 
11
11
  attr_accessible :name, :active, :address1, :address2, :city, :zipcode,
12
- :state_name, :state_id, :country_id, :phone, :country_id
12
+ :backorderable_default, :state_name, :state_id, :country_id, :phone,
13
+ :country_id, :propagate_all_variants
13
14
 
14
15
  scope :active, -> { where(active: true) }
15
16
 
16
- after_create :create_stock_items
17
+ after_create :create_stock_items, :if => "self.propagate_all_variants?"
18
+
19
+ # Wrapper for creating a new stock item respecting the backorderable config
20
+ def propagate_variant(variant)
21
+ self.stock_items.create!(variant: variant, backorderable: self.backorderable_default)
22
+ end
23
+
24
+ # Return either an existing stock item or create a new one. Useful in
25
+ # scenarios where the user might not know whether there is already a stock
26
+ # item for a given variant
27
+ def set_up_stock_item(variant)
28
+ self.stock_item(variant) || propagate_variant(variant)
29
+ end
17
30
 
18
31
  def stock_item(variant)
19
32
  stock_items.where(variant_id: variant).order(:id).first
@@ -63,11 +76,8 @@ module Spree
63
76
  end
64
77
 
65
78
  private
66
-
67
79
  def create_stock_items
68
- Spree::Variant.find_each do |v|
69
- self.stock_items.create!(variant: v)
70
- end
80
+ Variant.find_each { |variant| self.propagate_variant(variant) }
71
81
  end
72
82
  end
73
83
  end
@@ -1,5 +1,6 @@
1
1
  module Spree
2
2
  class TaxCategory < ActiveRecord::Base
3
+ acts_as_paranoid
3
4
  validates :name, presence: true, uniqueness: { scope: :deleted_at }
4
5
 
5
6
  has_many :tax_rates, dependent: :destroy
@@ -8,8 +9,6 @@ module Spree
8
9
 
9
10
  before_save :set_default_category
10
11
 
11
- default_scope where(deleted_at: nil)
12
-
13
12
  def set_default_category
14
13
  #set existing default tax category to false if this one has been marked as default
15
14
 
@@ -17,10 +16,5 @@ module Spree
17
16
  tax_category.update_column(:is_default, false) unless tax_category == self
18
17
  end
19
18
  end
20
-
21
- def mark_deleted!
22
- self.deleted_at = Time.now
23
- save
24
- end
25
19
  end
26
20
  end
@@ -10,6 +10,7 @@ end
10
10
 
11
11
  module Spree
12
12
  class TaxRate < ActiveRecord::Base
13
+ acts_as_paranoid
13
14
  include Spree::Core::CalculatedAdjustments
14
15
  belongs_to :zone, class_name: "Spree::Zone"
15
16
  belongs_to :tax_category, class_name: "Spree::TaxCategory"
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Variant < ActiveRecord::Base
3
+ acts_as_paranoid
4
+
3
5
  belongs_to :product, touch: true, class_name: 'Spree::Product'
4
6
 
5
7
  delegate_belongs_to :product, :name, :description, :permalink, :available_on,
@@ -14,7 +16,7 @@ module Spree
14
16
  has_many :inventory_units
15
17
  has_many :line_items
16
18
 
17
- has_many :stock_items, dependent: :destroy
19
+ has_many :stock_items, dependent: :destroy, :order => "id ASC"
18
20
  has_many :stock_locations, through: :stock_items
19
21
  has_many :stock_movements
20
22
 
@@ -133,6 +135,17 @@ module Spree
133
135
  Spree::Stock::Quantifier.new(self).can_supply?(quantity)
134
136
  end
135
137
 
138
+ def total_on_hand
139
+ Spree::Stock::Quantifier.new(self).total_on_hand
140
+ end
141
+
142
+ # Product may be created with deleted_at already set,
143
+ # which would make AR's default finder return nil.
144
+ # This is a stopgap for that little problem.
145
+ def product
146
+ Spree::Product.unscoped { super }
147
+ end
148
+
136
149
  private
137
150
  # strips all non-price-like characters from the price, taking into account locale settings
138
151
  def parse_price(price)
@@ -167,8 +180,8 @@ module Spree
167
180
  end
168
181
 
169
182
  def create_stock_items
170
- Spree::StockLocation.all.each do |stock_location|
171
- stock_location.stock_items.create!(variant: self)
183
+ StockLocation.all.each do |stock_location|
184
+ stock_location.propagate_variant(self) if stock_location.propagate_all_variants?
172
185
  end
173
186
  end
174
187
 
@@ -18,7 +18,7 @@ module Spree
18
18
 
19
19
  def kind
20
20
  if members.any? && !members.any? { |member| member.try(:zoneable_type).nil? }
21
- members.last.zoneable_type.demodulize.downcase
21
+ members.last.zoneable_type.demodulize.underscore
22
22
  end
23
23
  end
24
24
 
@@ -18,7 +18,7 @@ Spree::Core::Engine.config.to_prepare do
18
18
  end
19
19
 
20
20
  def last_incomplete_spree_order
21
- spree_orders.incomplete.order('created_at DESC').first
21
+ spree_orders.incomplete.where(:created_by_id => self.id).order('created_at DESC').first
22
22
  end
23
23
  end
24
24
  end
@@ -193,6 +193,12 @@ en:
193
193
  spree/zone:
194
194
  one: Zone
195
195
  other: Zones
196
+ errors:
197
+ models:
198
+ spree/credit_card:
199
+ attributes:
200
+ base:
201
+ card_expired: "Card has expired"
196
202
  devise:
197
203
  confirmations:
198
204
  confirmed: Your account was successfully confirmed. You are now signed in.
@@ -295,6 +301,7 @@ en:
295
301
  reports: "Reports"
296
302
  configuration: "Configuration"
297
303
  promotions: "Promotions"
304
+ users: "Users"
298
305
  administration: Administration
299
306
  agree_to_privacy_policy: Agree to Privacy Policy
300
307
  agree_to_terms_of_service: Agree to Terms of Service
@@ -343,7 +350,7 @@ en:
343
350
  back_to_shipping_categories: Back To Shipping Categories
344
351
  back_to_shipping_methods_list: Back To Shipping Methods List
345
352
  back_to_states_list: Back To States List
346
- back_to_stock_locations_list: Back to Stock Movements List
353
+ back_to_stock_locations_list: Back to Stock Locations List
347
354
  back_to_stock_movements_list: Back to Stock Movements List
348
355
  back_to_stock_transfers_list: Back to Stock Transfers List
349
356
  back_to_store: Go Back To Store
@@ -583,6 +590,7 @@ en:
583
590
  operators:
584
591
  gt: greater than
585
592
  gte: greater than or equal to
593
+ items_cannot_be_shipped: We are unable to ship the selected items to your shipping address. Please choose another shipping address.
586
594
  jirafe: Jirafe
587
595
  landing_page_rule:
588
596
  path: Path
@@ -661,12 +669,14 @@ en:
661
669
  no_actions_added: No actions added
662
670
  no_orders_found: No orders found
663
671
  no_payment_methods_found: No payment methods found
672
+ no_pending_payments: No pending payments
664
673
  no_products_found: No products found
665
674
  no_promotions_found: No promotions found
666
675
  no_results: No results
667
676
  no_rules_added: No rules added
668
677
  no_shipping_methods_found: No shipping methods found
669
678
  no_trackers_found: No Trackers Found
679
+ no_stock_locations_found: No stock locations found
670
680
  no_tracking_present: No tracking details provided.
671
681
  none: None
672
682
  normal_amount: Normal Amount
@@ -685,6 +695,7 @@ en:
685
695
  open: Open
686
696
  open_all_adjustments: Open All Adjustments
687
697
  option_type: Option Type
698
+ option_type_placeholder: Choose an option type
688
699
  option_types: Option Types
689
700
  option_value: Option Value
690
701
  option_values: Option Values
@@ -965,6 +976,7 @@ en:
965
976
  stock_location_info: Stock location info
966
977
  stock_locations: Stock Locations
967
978
  stock_management: Stock Management
979
+ stock_management_requires_a_stock_location: Please create a stock location in order to manage stock.
968
980
  stock_movements: Stock Movements
969
981
  stock_movements_for_stock_location: Stock Movements for %{stock_location_name}
970
982
  stock_successfully_transferred: Stock was successfully transferred between locations.
@@ -1004,6 +1016,7 @@ en:
1004
1016
  subject: Test Mail
1005
1017
  test_mode: Test Mode
1006
1018
  thank_you_for_your_order: Thank you for your business. Please print out a copy of this confirmation page for your records.
1019
+ there_are_no_items_for_this_order: There are no items for this order. Please add an item to the order to continue.
1007
1020
  there_were_problems_with_the_following_fields: There were problems with the following fields
1008
1021
  thumbnail: Thumbnail
1009
1022
  time: Time
@@ -1043,6 +1056,7 @@ en:
1043
1056
  must_be_non_negative: must be a non-negative value
1044
1057
  value: Value
1045
1058
  variant: Variant
1059
+ variant_placeholder: Choose a variant
1046
1060
  variants: Variants
1047
1061
  version: Version
1048
1062
  void: Void
@@ -4,7 +4,12 @@ class CreateShippingMethodZone < ActiveRecord::Migration
4
4
  t.integer :shipping_method_id
5
5
  t.integer :zone_id
6
6
  end
7
-
7
+ # This association has been corrected in a latter migration
8
+ # but when this database migration runs, the table is still incorrectly named
9
+ # 'shipping_methods_zones' instead of 'spre_shipping_methods_zones'
10
+ Spree::ShippingMethod.has_and_belongs_to_many :zones, :join_table => 'shipping_methods_zones',
11
+ :class_name => 'Spree::Zone',
12
+ :foreign_key => 'shipping_method_id'
8
13
  Spree::ShippingMethod.all.each{|sm| sm.zones << Spree::Zone.find(sm.zone_id)}
9
14
 
10
15
  remove_column :spree_shipping_methods, :zone_id
@@ -13,7 +13,10 @@ class AddAddressFieldsToStockLocation < ActiveRecord::Migration
13
13
 
14
14
 
15
15
  usa = Spree::Country.where(:iso => 'US').first
16
+ # In case USA isn't found.
17
+ # See #3115
18
+ country = usa || Spree::Country.first
16
19
  Spree::Country.reset_column_information
17
- Spree::StockLocation.update_all(:country_id => usa)
20
+ Spree::StockLocation.update_all(:country_id => country)
18
21
  end
19
22
  end
@@ -0,0 +1,5 @@
1
+ class AddBackorderableDefaultToSpreeStockLocation < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_stock_locations, :backorderable_default, :boolean, default: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddPropageAllVariantsToSpreeStockLocation < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_stock_locations, :propagate_all_variants, :boolean, default: true
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddCvvResultCodeAndCvvResultMessageToSpreePayments < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_payments, :cvv_response_code, :string
4
+ add_column :spree_payments, :cvv_response_message, :string
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddUniqueIndexToPermalinkOnSpreeProducts < ActiveRecord::Migration
2
+ def change
3
+ add_index "spree_products", ["permalink"], :name => "permalink_idx_unique", :unique => true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class AddUniqueIndexToOrdersShipmentsAndStockTransfers < ActiveRecord::Migration
2
+ def add
3
+ add_index "spree_orders", ["number"], :name => "number_idx_unique", :unique => true
4
+ add_index "spree_shipments", ["number"], :name => "number_idx_unique", :unique => true
5
+ add_index "spree_stock_transfers", ["number"], :name => "number_idx_unique", :unique => true
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeletedAtToSpreeTaxRates < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_tax_rates, :deleted_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class RemoveLockVersionFromInventoryUnits < ActiveRecord::Migration
2
+ def change
3
+ # we are moving to pessimistic locking on stock_items
4
+ remove_column :spree_inventory_units, :lock_version
5
+ end
6
+ end