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.
- checksums.yaml +4 -4
- data/app/assets/images/logo/spree_50.png +0 -0
- data/app/assets/images/noimage/large.png +0 -0
- data/app/assets/images/noimage/mini.png +0 -0
- data/app/assets/images/noimage/product.png +0 -0
- data/app/assets/images/noimage/small.png +0 -0
- data/app/controllers/spree/base_controller.rb +3 -0
- data/app/helpers/spree/base_helper.rb +15 -11
- data/app/models/spree/adjustment.rb +5 -0
- data/app/models/spree/app_configuration.rb +3 -3
- data/app/models/spree/calculator/default_tax.rb +2 -2
- data/app/models/spree/calculator/percent_per_item.rb +9 -5
- data/app/models/spree/calculator.rb +1 -1
- data/app/models/spree/credit_card.rb +25 -0
- data/app/models/spree/line_item.rb +9 -0
- data/app/models/spree/new_adjustment.rb +4 -0
- data/app/models/spree/order/checkout.rb +4 -5
- data/app/models/spree/order.rb +52 -25
- data/app/models/spree/order_contents.rb +8 -7
- data/app/models/spree/order_inventory.rb +13 -13
- data/app/models/spree/order_populator.rb +4 -14
- data/app/models/spree/order_updater.rb +1 -1
- data/app/models/spree/payment/processing.rb +5 -0
- data/app/models/spree/payment.rb +12 -1
- data/app/models/spree/payment_method.rb +1 -4
- data/app/models/spree/product.rb +44 -17
- data/app/models/spree/promotion/actions/create_adjustment.rb +1 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +32 -2
- data/app/models/spree/promotion.rb +2 -1
- data/app/models/spree/shipment.rb +5 -5
- data/app/models/spree/shipping_adjustment.rb +4 -0
- data/app/models/spree/shipping_method.rb +6 -0
- data/app/models/spree/shipping_rate.rb +1 -0
- data/app/models/spree/stock/availability_validator.rb +5 -3
- data/app/models/spree/stock/coordinator.rb +16 -4
- data/app/models/spree/stock/estimator.rb +16 -6
- data/app/models/spree/stock/packer.rb +2 -1
- data/app/models/spree/stock_location.rb +16 -6
- data/app/models/spree/tax_category.rb +1 -7
- data/app/models/spree/tax_rate.rb +1 -0
- data/app/models/spree/variant.rb +16 -3
- data/app/models/spree/zone.rb +1 -1
- data/config/initializers/user_class_extensions.rb +1 -1
- data/config/locales/en.yml +15 -1
- data/db/migrate/20130228210442_create_shipping_method_zone.rb +6 -1
- data/db/migrate/20130306181701_add_address_fields_to_stock_location.rb +4 -1
- data/db/migrate/20130515180736_add_backorderable_default_to_spree_stock_location.rb +5 -0
- data/db/migrate/20130516151222_add_propage_all_variants_to_spree_stock_location.rb +5 -0
- data/db/migrate/20130626232741_add_cvv_result_code_and_cvv_result_message_to_spree_payments.rb +6 -0
- data/db/migrate/20130628021056_add_unique_index_to_permalink_on_spree_products.rb +5 -0
- data/db/migrate/20130628022817_add_unique_index_to_orders_shipments_and_stock_transfers.rb +7 -0
- data/db/migrate/20130708052307_add_deleted_at_to_spree_tax_rates.rb +5 -0
- data/db/migrate/20130711200933_remove_lock_version_from_inventory_units.rb +6 -0
- data/db/migrate/20130718042445_add_cost_price_to_line_item.rb +5 -0
- data/db/migrate/20130718233855_set_backorderable_to_default_to_false.rb +6 -0
- data/db/migrate/20130725031716_add_created_by_id_to_spree_orders.rb +5 -0
- data/db/migrate/20130729214043_index_completed_at_on_spree_orders.rb +5 -0
- data/db/migrate/20130802014537_add_tax_category_id_to_spree_line_items.rb +5 -0
- data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +9 -0
- data/db/migrate/20130805043440_create_spree_new_adjustments.rb +8 -0
- data/lib/generators/spree/dummy/templates/rails/database.yml +8 -7
- data/lib/generators/spree/install/install_generator.rb +1 -1
- data/lib/spree/core/calculated_adjustments.rb +12 -1
- data/lib/spree/core/controller_helpers/order.rb +5 -3
- data/lib/spree/core/controller_helpers/search.rb +14 -0
- data/lib/spree/core/permalinks.rb +13 -13
- data/lib/spree/core/s3_support.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +7 -5
- data/lib/spree/i18n/base.rb +17 -0
- data/lib/spree/i18n/initializer.rb +1 -0
- data/lib/spree/i18n.rb +28 -7
- data/lib/spree/money.rb +2 -0
- data/lib/spree/testing_support/authorization_helpers.rb +6 -15
- data/lib/spree/testing_support/capybara_ext.rb +20 -11
- data/lib/spree/testing_support/common_rake.rb +13 -0
- data/lib/spree/testing_support/factories/country_factory.rb +1 -1
- data/lib/spree/testing_support/factories/order_factory.rb +0 -2
- data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -1
- data/lib/spree/testing_support/factories/product_factory.rb +8 -18
- data/lib/spree/testing_support/factories/return_authorization_factory.rb +4 -0
- data/lib/spree/testing_support/factories/shipment_factory.rb +1 -1
- data/lib/spree/testing_support/factories/stock_item_factory.rb +2 -1
- data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -2
- data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +14 -1
- data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
- metadata +118 -67
data/app/models/spree/product.rb
CHANGED
@@ -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
|
-
|
48
|
-
|
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,
|
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 :
|
75
|
-
:
|
76
|
-
:
|
77
|
-
:
|
78
|
-
:
|
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
|
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
|
-
|
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.
|
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
|
@@ -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?
|
@@ -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
|
-
|
10
|
-
|
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 =
|
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
|
-
|
18
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
data/app/models/spree/variant.rb
CHANGED
@@ -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
|
-
|
171
|
-
stock_location.
|
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
|
|
data/app/models/spree/zone.rb
CHANGED
data/config/locales/en.yml
CHANGED
@@ -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
|
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 =>
|
20
|
+
Spree::StockLocation.update_all(:country_id => country)
|
18
21
|
end
|
19
22
|
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
|