spree_core 2.4.0.rc2 → 2.4.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/products_helper.rb +7 -8
  3. data/app/models/spree/adjustment.rb +7 -2
  4. data/app/models/spree/classification.rb +1 -1
  5. data/app/models/spree/exchange.rb +4 -0
  6. data/app/models/spree/gateway/bogus.rb +3 -2
  7. data/app/models/spree/inventory_unit.rb +1 -1
  8. data/app/models/spree/item_adjustments.rb +7 -3
  9. data/app/models/spree/line_item.rb +5 -0
  10. data/app/models/spree/order.rb +3 -3
  11. data/app/models/spree/order_contents.rb +11 -14
  12. data/app/models/spree/payment.rb +7 -3
  13. data/app/models/spree/payment_method/check.rb +2 -0
  14. data/app/models/spree/payment_method.rb +5 -1
  15. data/app/models/spree/product.rb +11 -8
  16. data/app/models/spree/promotion/actions/create_item_adjustments.rb +3 -2
  17. data/app/models/spree/promotion/actions/create_line_items.rb +1 -0
  18. data/app/models/spree/promotion.rb +2 -2
  19. data/app/models/spree/promotion_handler/coupon.rb +5 -1
  20. data/app/models/spree/property.rb +0 -7
  21. data/app/models/spree/prototype.rb +1 -0
  22. data/app/models/spree/reimbursement.rb +1 -1
  23. data/app/models/spree/reimbursement_tax_calculator.rb +7 -1
  24. data/app/models/spree/return_authorization.rb +1 -1
  25. data/app/models/spree/shipping_category.rb +2 -2
  26. data/app/models/spree/shipping_method_category.rb +1 -1
  27. data/app/models/spree/stock/package.rb +6 -0
  28. data/app/models/spree/stock_item.rb +2 -2
  29. data/app/models/spree/stock_location.rb +1 -1
  30. data/app/models/spree/store.rb +1 -1
  31. data/app/models/spree/tax_category.rb +2 -2
  32. data/app/models/spree/tax_rate.rb +7 -4
  33. data/app/models/spree/taxon.rb +7 -3
  34. data/app/models/spree/variant.rb +5 -5
  35. data/app/models/spree/zone.rb +15 -17
  36. data/app/models/spree/zone_member.rb +1 -1
  37. data/config/initializers/user_class_extensions.rb +10 -9
  38. data/config/locales/en.yml +1 -0
  39. data/db/default/spree/countries.rb +18 -231
  40. data/db/default/spree/states.rb +16 -76
  41. data/db/development.sqlite +0 -0
  42. data/db/migrate/20130213191427_create_default_stock.rb +4 -1
  43. data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +3 -5
  44. data/db/migrate/20140717185932_add_default_to_spree_stock_locations.rb +3 -1
  45. data/db/migrate/20141012083513_create_spree_taxons_prototypes.rb +8 -0
  46. data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +5 -0
  47. data/db/migrate/20141023005240_add_counter_cache_from_spree_variants_to_spree_stock_items.rb +13 -0
  48. data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +13 -0
  49. data/db/migrate/20141105213646_update_classifications_positions.rb +9 -0
  50. data/lib/generators/spree/install/install_generator.rb +3 -7
  51. data/lib/spree/core/controller_helpers/order.rb +5 -6
  52. data/lib/spree/core/importer/order.rb +16 -3
  53. data/lib/spree/core/search/base.rb +1 -1
  54. data/lib/spree/core/validators/email.rb +1 -1
  55. data/lib/spree/core/version.rb +1 -1
  56. data/lib/spree/migrations.rb +7 -3
  57. data/lib/spree/permitted_attributes.rb +3 -1
  58. data/lib/spree/testing_support/ability_helpers.rb +25 -25
  59. data/lib/spree/testing_support/capybara_ext.rb +2 -2
  60. data/lib/spree/testing_support/factories/customer_return_factory.rb +1 -1
  61. data/lib/spree/testing_support/factories/line_item_factory.rb +1 -1
  62. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  63. data/lib/spree/testing_support/factories/product_factory.rb +6 -0
  64. data/lib/spree/testing_support/factories/promotion_factory.rb +3 -3
  65. data/lib/spree/testing_support/factories/reimbursement_factory.rb +1 -1
  66. data/lib/spree/testing_support/factories/stock_factory.rb +3 -3
  67. data/lib/spree/testing_support/flash.rb +2 -2
  68. metadata +30 -17
  69. data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +0 -23
  70. data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +0 -25
  71. data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +0 -25
  72. data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +0 -25
  73. data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +0 -25
  74. data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +0 -25
  75. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +0 -26
  76. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +0 -26
  77. data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +0 -25
  78. data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +0 -23
  79. data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +0 -25
  80. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +0 -25
  81. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c974cc01f67cfca0ddbf2139e93097dfb45213d4
4
- data.tar.gz: cd6f74faba0892c17ed5bce5394c714f832c7588
3
+ metadata.gz: 3ad557fa8765c3b9bd3d6532c913962d33865e28
4
+ data.tar.gz: c424bb23636fd0889e52830a5905bb48069e2440
5
5
  SHA512:
6
- metadata.gz: 9c217028bbe1b3368d612db4293985921e4e4502c2564b0574f2af8c9621bb0abf86ceb694bab9ff2fad4e33022646676d962b88d4c76430e0a539cb4417cc63
7
- data.tar.gz: 50f73eeaf2728c151cf88932519af67a4836b0a96cd4401d9ff45ee8de3fae597e5e8bb25e25b640ad2497b6aabf0379bc5b93a531766d109f25013698f06c15
6
+ metadata.gz: bc7f1a23e33514c7b732f8c154dad4310c7bf3f2a617eabb5b138d97516d6ea0f67edfca2e4e20fc6d59a4bda1ff0a1d37aab2b1f1888b715a8d31ea617faa81
7
+ data.tar.gz: f5b67b3fe498f7e92d50cf242df7b9638304563348efd0ff6fbaeedd8bbe653fb971b566224b9d44763c71608d77edecdd652d00728c77face10db1f3aff2d75
@@ -11,14 +11,13 @@ module Spree
11
11
 
12
12
  # returns the formatted price for the specified variant as a difference from product price
13
13
  def variant_price_diff(variant)
14
- diff = variant.amount_in(current_currency) - variant.product.amount_in(current_currency)
15
- return nil if diff == 0
16
- amount = Spree::Money.new(diff.abs, { currency: current_currency }).to_html
17
- if diff > 0
18
- "(#{Spree.t(:add)}: #{amount})".html_safe
19
- else
20
- "(#{Spree.t(:subtract)}: #{amount})".html_safe
21
- end
14
+ variant_amount = variant.amount_in(current_currency)
15
+ product_amount = variant.product.amount_in(current_currency)
16
+ return if variant_amount == product_amount || product_amount.nil?
17
+ diff = variant.amount_in(current_currency) - product_amount
18
+ amount = Spree::Money.new(diff.abs, currency: current_currency).to_html
19
+ label = diff > 0 ? :add : :subtract
20
+ "(#{Spree.t(label)}: #{amount})".html_safe
22
21
  end
23
22
 
24
23
  # returns the formatted full price for the variant, if at least one variant price differs from product price
@@ -26,6 +26,8 @@ module Spree
26
26
  belongs_to :source, polymorphic: true
27
27
  belongs_to :order, class_name: "Spree::Order"
28
28
 
29
+ validates :adjustable, presence: true
30
+ validates :order, presence: true
29
31
  validates :label, presence: true
30
32
  validates :amount, numericality: true
31
33
 
@@ -45,7 +47,10 @@ module Spree
45
47
  scope :open, -> { where(state: 'open') }
46
48
  scope :closed, -> { where(state: 'closed') }
47
49
  scope :tax, -> { where(source_type: 'Spree::TaxRate') }
48
- scope :non_tax, -> { where.not(source_type: 'Spree::TaxRate') }
50
+ scope :non_tax, -> do
51
+ source_type = arel_table[:source_type]
52
+ where(source_type.not_eq('Spree::TaxRate').or source_type.eq(nil))
53
+ end
49
54
  scope :price, -> { where(adjustable_type: 'Spree::LineItem') }
50
55
  scope :shipping, -> { where(adjustable_type: 'Spree::Shipment') }
51
56
  scope :optional, -> { where(mandatory: false) }
@@ -103,7 +108,7 @@ module Spree
103
108
 
104
109
  def update_adjustable_adjustment_total
105
110
  # Cause adjustable's total to be recalculated
106
- Spree::ItemAdjustments.new(adjustable).update if adjustable
111
+ ItemAdjustments.new(adjustable).update
107
112
  end
108
113
 
109
114
  end
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Classification < Spree::Base
3
3
  self.table_name = 'spree_products_taxons'
4
- acts_as_list
4
+ acts_as_list scope: :taxon
5
5
  belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications
6
6
  belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications
7
7
 
@@ -1,5 +1,6 @@
1
1
  module Spree
2
2
  class Exchange
3
+ class UnableToCreateShipments < StandardError; end
3
4
 
4
5
  def initialize(order, reimbursement_objects)
5
6
  @order = order
@@ -18,6 +19,9 @@ module Spree
18
19
 
19
20
  def perform!
20
21
  shipments = Spree::Stock::Coordinator.new(@order, @reimbursement_objects.map(&:build_exchange_inventory_unit)).shipments
22
+ if shipments.flat_map(&:inventory_units).size != @reimbursement_objects.size
23
+ raise UnableToCreateShipments.new("Could not generate shipments for all items. Out of stock?")
24
+ end
21
25
  @order.shipments += shipments
22
26
  @order.save!
23
27
  shipments.each do |shipment|
@@ -20,8 +20,9 @@ module Spree
20
20
  def create_profile(payment)
21
21
  return if payment.source.has_payment_profile?
22
22
  # simulate the storage of credit card profile using remote service
23
- success = VALID_CCS.include? payment.source.number
24
- payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
23
+ if success = VALID_CCS.include?(payment.source.number)
24
+ payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
25
+ end
25
26
  end
26
27
 
27
28
  def authorize(money, credit_card, options = {})
@@ -3,7 +3,7 @@ module Spree
3
3
  belongs_to :variant, class_name: "Spree::Variant", inverse_of: :inventory_units
4
4
  belongs_to :order, class_name: "Spree::Order", inverse_of: :inventory_units
5
5
  belongs_to :shipment, class_name: "Spree::Shipment", touch: true, inverse_of: :inventory_units
6
- belongs_to :return_authorization, class_name: "Spree::ReturnAuthorization"
6
+ belongs_to :return_authorization, class_name: "Spree::ReturnAuthorization", inverse_of: :inventory_units
7
7
  belongs_to :line_item, class_name: "Spree::LineItem", inverse_of: :inventory_units
8
8
 
9
9
  has_many :return_items, inverse_of: :inventory_unit
@@ -9,8 +9,9 @@ module Spree
9
9
 
10
10
  def initialize(item)
11
11
  @item = item
12
+
12
13
  # Don't attempt to reload the item from the DB if it's not there
13
- @item.reload if @item.persisted?
14
+ @item.reload if @item.instance_of?(Shipment) && @item.persisted?
14
15
  end
15
16
 
16
17
  def update
@@ -27,7 +28,7 @@ module Spree
27
28
  #
28
29
  # It also fits the criteria for sales tax as outlined here:
29
30
  # http://www.boe.ca.gov/formspubs/pub113/
30
- #
31
+ #
31
32
  # Tax adjustments come in not one but *two* exciting flavours:
32
33
  # Included & additional
33
34
 
@@ -37,7 +38,10 @@ module Spree
37
38
  # Additional tax adjustments are the opposite, affecting the final total.
38
39
  promo_total = 0
39
40
  run_callbacks :promo_adjustments do
40
- promotion_total = adjustments.promotion.reload.map(&:update!).compact.sum
41
+ promotion_total = adjustments.promotion.reload.map do |adjustment|
42
+ adjustment.update!(@item)
43
+ end.compact.sum
44
+
41
45
  unless promotion_total == 0
42
46
  choose_best_promotion_adjustment
43
47
  end
@@ -24,6 +24,7 @@ module Spree
24
24
 
25
25
  validate :ensure_proper_currency
26
26
  before_destroy :update_inventory
27
+ before_destroy :destroy_inventory_units
27
28
 
28
29
  after_save :update_inventory
29
30
  after_save :update_adjustments
@@ -123,6 +124,10 @@ module Spree
123
124
  end
124
125
  end
125
126
 
127
+ def destroy_inventory_units
128
+ inventory_units.destroy_all
129
+ end
130
+
126
131
  def update_adjustments
127
132
  if quantity_changed?
128
133
  update_tax_charge # Called to ensure pre_tax_amount is updated.
@@ -45,9 +45,9 @@ module Spree
45
45
  alias_attribute :ship_total, :shipment_total
46
46
 
47
47
  has_many :state_changes, as: :stateful
48
- has_many :line_items, -> { order('created_at ASC') }, dependent: :destroy, inverse_of: :order
48
+ has_many :line_items, -> { order("#{LineItem.table_name}.created_at ASC") }, dependent: :destroy, inverse_of: :order
49
49
  has_many :payments, dependent: :destroy
50
- has_many :return_authorizations, dependent: :destroy
50
+ has_many :return_authorizations, dependent: :destroy, inverse_of: :order
51
51
  has_many :reimbursements, inverse_of: :order
52
52
  has_many :adjustments, -> { order("#{Adjustment.table_name}.created_at ASC") }, as: :adjustable, dependent: :destroy
53
53
  has_many :line_item_adjustments, through: :line_items, source: :adjustments
@@ -84,7 +84,7 @@ module Spree
84
84
 
85
85
  validates :email, presence: true, if: :require_email
86
86
  validates :email, email: true, if: :require_email, allow_blank: true
87
- validates :number, uniqueness: true
87
+ validates :number, presence: true, uniqueness: { allow_blank: true }
88
88
  validate :has_available_shipment
89
89
 
90
90
  make_permalink field: :number
@@ -8,24 +8,12 @@ module Spree
8
8
 
9
9
  def add(variant, quantity = 1, options = {})
10
10
  line_item = add_to_line_item(variant, quantity, options)
11
- reload_totals
12
- shipment = options[:shipment]
13
- shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
14
- PromotionHandler::Cart.new(order, line_item).activate
15
- ItemAdjustments.new(line_item).update
16
- reload_totals
17
- line_item
11
+ after_add_or_remove(line_item, options)
18
12
  end
19
13
 
20
14
  def remove(variant, quantity = 1, options = {})
21
15
  line_item = remove_from_line_item(variant, quantity, options)
22
- reload_totals
23
- shipment = options[:shipment]
24
- shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
25
- PromotionHandler::Cart.new(order, line_item).activate
26
- ItemAdjustments.new(line_item).update
27
- reload_totals
28
- line_item
16
+ after_add_or_remove(line_item, options)
29
17
  end
30
18
 
31
19
  def update_cart(params)
@@ -45,6 +33,15 @@ module Spree
45
33
  end
46
34
 
47
35
  private
36
+ def after_add_or_remove(line_item, options = {})
37
+ reload_totals
38
+ shipment = options[:shipment]
39
+ shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
40
+ PromotionHandler::Cart.new(order, line_item).activate
41
+ ItemAdjustments.new(line_item).update
42
+ reload_totals
43
+ line_item
44
+ end
48
45
 
49
46
  def filter_order_items(params)
50
47
  filtered_params = params.symbolize_keys
@@ -8,7 +8,7 @@ module Spree
8
8
 
9
9
  belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :payments
10
10
  belongs_to :source, polymorphic: true
11
- belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
11
+ belongs_to :payment_method, class_name: 'Spree::PaymentMethod', inverse_of: :payments
12
12
 
13
13
  has_many :offsets, -> { offset_payment }, class_name: "Spree::Payment", foreign_key: :source_id
14
14
  has_many :log_entries, as: :source
@@ -184,6 +184,8 @@ module Spree
184
184
  end
185
185
 
186
186
  def create_payment_profile
187
+ # Don't attempt to create on bad payments.
188
+ return if %w(invalid failed).include?(state)
187
189
  # Payment profile cannot be created without source
188
190
  return unless source
189
191
  # Imported payments shouldn't create a payment profile.
@@ -195,8 +197,10 @@ module Spree
195
197
  end
196
198
 
197
199
  def invalidate_old_payments
198
- order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
199
- payment.invalidate!
200
+ if state != 'invalid' and state != 'failed'
201
+ order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
202
+ payment.invalidate!
203
+ end
200
204
  end
201
205
  end
202
206
 
@@ -18,6 +18,8 @@ module Spree
18
18
  ActiveMerchant::Billing::Response.new(true, "", {}, {})
19
19
  end
20
20
 
21
+ def cancel(response); end
22
+
21
23
  def void(*args)
22
24
  ActiveMerchant::Billing::Response.new(true, "", {}, {})
23
25
  end
@@ -8,7 +8,7 @@ module Spree
8
8
 
9
9
  validates :name, presence: true
10
10
 
11
- has_many :payments, class_name: "Spree::Payment"
11
+ has_many :payments, class_name: "Spree::Payment", inverse_of: :payment_method
12
12
  has_many :credit_cards, class_name: "Spree::CreditCard"
13
13
 
14
14
  def self.providers
@@ -67,5 +67,9 @@ module Spree
67
67
  def supports?(source)
68
68
  true
69
69
  end
70
+
71
+ def cancel
72
+ raise NotImplimentedError.new 'You must implement cancel method for this payment method.'
73
+ end
70
74
  end
71
75
  end
@@ -40,8 +40,7 @@ module Spree
40
40
  has_one :master,
41
41
  -> { where is_master: true },
42
42
  inverse_of: :product,
43
- class_name: 'Spree::Variant',
44
- dependent: :destroy
43
+ class_name: 'Spree::Variant'
45
44
 
46
45
  has_many :variants,
47
46
  -> { where(is_master: false).order("#{::Spree::Variant.quoted_table_name}.position ASC") },
@@ -57,7 +56,7 @@ module Spree
57
56
  has_many :prices, -> { order('spree_variants.position, spree_variants.id, currency') }, through: :variants
58
57
 
59
58
  has_many :stock_items, through: :variants_including_master
60
-
59
+
61
60
  has_many :line_items, through: :variants_including_master
62
61
  has_many :orders, through: :line_items
63
62
 
@@ -66,7 +65,7 @@ module Spree
66
65
  delegate_belongs_to :master, :cost_price
67
66
 
68
67
  after_create :set_master_variant_defaults
69
- after_create :add_properties_and_option_types_from_prototype
68
+ after_create :add_associations_from_prototype
70
69
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
71
70
 
72
71
  after_save :save_master
@@ -83,7 +82,10 @@ module Spree
83
82
  validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
84
83
  validates :shipping_category_id, presence: true
85
84
  validates :slug, length: { minimum: 3 }
86
- validates :slug, uniqueness: true
85
+
86
+ validates :slug, uniqueness: { allow_blank: true }
87
+ validates :meta_keywords, length: { maximum: 255 }
88
+ validates :meta_title, length: { maximum: 255 }
87
89
 
88
90
  before_validation :normalize_slug, on: :update
89
91
 
@@ -219,12 +221,13 @@ module Spree
219
221
 
220
222
  private
221
223
 
222
- def add_properties_and_option_types_from_prototype
224
+ def add_associations_from_prototype
223
225
  if prototype_id && prototype = Spree::Prototype.find_by(id: prototype_id)
224
226
  prototype.properties.each do |property|
225
227
  product_properties.create(property: property)
226
228
  end
227
229
  self.option_types = prototype.option_types
230
+ self.taxons = prototype.taxons
228
231
  end
229
232
  end
230
233
 
@@ -300,8 +303,8 @@ module Spree
300
303
  # Try building a slug based on the following fields in increasing order of specificity.
301
304
  def slug_candidates
302
305
  [
303
- :name,
304
- [:name, :sku]
306
+ :name,
307
+ [:name, :sku]
305
308
  ]
306
309
  end
307
310
 
@@ -40,9 +40,10 @@ module Spree
40
40
  # Ensure a negative amount which does not exceed the sum of the order's
41
41
  # item_total and ship_total
42
42
  def compute_amount(adjustable)
43
- return 0 unless promotion.line_item_actionable? adjustable.order, adjustable
43
+ order = adjustable.is_a?(Order) ? adjustable : adjustable.order
44
+ return 0 unless promotion.line_item_actionable?(order, adjustable)
44
45
  promotion_amount = self.calculator.compute(adjustable).to_f.abs
45
-
46
+
46
47
  [adjustable.amount, promotion_amount].min * -1
47
48
  end
48
49
 
@@ -45,6 +45,7 @@ module Spree
45
45
  order.contents.add(item.variant, item.quantity - current_quantity)
46
46
  end
47
47
  end
48
+ true
48
49
  end
49
50
  end
50
51
  end
@@ -20,7 +20,7 @@ module Spree
20
20
  validates_associated :rules
21
21
 
22
22
  validates :name, presence: true
23
- validates :path, uniqueness: true, allow_blank: true
23
+ validates :path, uniqueness: { allow_blank: true }
24
24
  validates :usage_limit, numericality: { greater_than: 0, allow_nil: true }
25
25
  validates :description, length: { maximum: 255 }
26
26
 
@@ -37,7 +37,7 @@ module Spree
37
37
  end
38
38
 
39
39
  def self.with_coupon_code(coupon_code)
40
- where("lower(code) = ?", coupon_code.strip.downcase).first
40
+ where("lower(#{self.table_name}.code) = ?", coupon_code.strip.downcase).first
41
41
  end
42
42
 
43
43
  def self.active
@@ -85,11 +85,15 @@ module Spree
85
85
  end
86
86
  }
87
87
 
88
+ # Check for applied adjustments.
88
89
  discount = order.line_item_adjustments.promotion.detect(&detector)
89
90
  discount ||= order.shipment_adjustments.promotion.detect(&detector)
90
91
  discount ||= order.adjustments.promotion.detect(&detector)
91
92
 
92
- if discount.eligible
93
+ # Check for applied line items.
94
+ created_line_items = promotion.actions.detect { |a| a.type == 'Spree::Promotion::Actions::CreateLineItems' }
95
+
96
+ if (discount && discount.eligible) || created_line_items
93
97
  order.update_totals
94
98
  order.persist_totals
95
99
  set_success_code :coupon_code_applied
@@ -11,13 +11,6 @@ module Spree
11
11
 
12
12
  after_touch :touch_all_products
13
13
 
14
- def self.find_all_by_prototype(prototype)
15
- id = prototype
16
- id = prototype.id if prototype.class == Prototype
17
- joins("LEFT JOIN properties_prototypes ON property_id = #{self.table_name}.id").
18
- where(prototype_id: id)
19
- end
20
-
21
14
  private
22
15
 
23
16
  def touch_all_products
@@ -2,6 +2,7 @@ module Spree
2
2
  class Prototype < Spree::Base
3
3
  has_and_belongs_to_many :properties, join_table: :spree_properties_prototypes
4
4
  has_and_belongs_to_many :option_types, join_table: :spree_option_types_prototypes
5
+ has_and_belongs_to_many :taxons, join_table: :spree_taxons_prototypes
5
6
 
6
7
  validates :name, presence: true
7
8
  end
@@ -55,7 +55,6 @@ module Spree
55
55
  self.reimbursement_failure_hooks = []
56
56
 
57
57
  state_machine :reimbursement_status, initial: :pending do
58
- after_transition to: :reimbursed, do: :send_reimbursement_email
59
58
 
60
59
  event :errored do
61
60
  transition to: :errored, from: :pending
@@ -107,6 +106,7 @@ module Spree
107
106
  if unpaid_amount.zero?
108
107
  reimbursed!
109
108
  reimbursement_success_hooks.each { |h| h.call self }
109
+ send_reimbursement_email
110
110
  else
111
111
  errored!
112
112
  reimbursement_failure_hooks.each { |h| h.call self }
@@ -21,7 +21,13 @@ module Spree
21
21
  private
22
22
 
23
23
  def set_tax!(return_item)
24
- percent_of_tax = (return_item.pre_tax_amount <= 0) ? 0 : return_item.pre_tax_amount / Spree::ReturnItem.refund_amount_calculator.new.compute(return_item)
24
+ calculated_refund = Spree::ReturnItem.refund_amount_calculator.new.compute(return_item)
25
+
26
+ percent_of_tax = if return_item.pre_tax_amount <= 0 || calculated_refund <= 0
27
+ 0
28
+ else
29
+ return_item.pre_tax_amount / calculated_refund
30
+ end
25
31
 
26
32
  additional_tax_total = percent_of_tax * return_item.inventory_unit.additional_tax_total
27
33
  included_tax_total = percent_of_tax * return_item.inventory_unit.included_tax_total
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class ReturnAuthorization < Spree::Base
3
- belongs_to :order, class_name: 'Spree::Order'
3
+ belongs_to :order, class_name: 'Spree::Order', inverse_of: :return_authorizations
4
4
 
5
5
  has_many :return_items, inverse_of: :return_authorization, dependent: :destroy
6
6
  has_many :inventory_units, through: :return_items
@@ -2,7 +2,7 @@ module Spree
2
2
  class ShippingCategory < Spree::Base
3
3
  validates :name, presence: true
4
4
  has_many :products, inverse_of: :shipping_category
5
- has_many :shipping_method_categories
5
+ has_many :shipping_method_categories, inverse_of: :shipping_method
6
6
  has_many :shipping_methods, through: :shipping_method_categories
7
7
  end
8
- end
8
+ end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class ShippingMethodCategory < Spree::Base
3
3
  belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
4
- belongs_to :shipping_category, class_name: 'Spree::ShippingCategory'
4
+ belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
5
5
  end
6
6
  end
@@ -23,6 +23,12 @@ module Spree
23
23
  @contents -= [item] if item
24
24
  end
25
25
 
26
+ # Fix regression that removed package.order.
27
+ # Find it dynamically through an inventory_unit.
28
+ def order
29
+ contents.detect {|item| !!item.try(:inventory_unit).try(:order) }.try(:inventory_unit).try(:order)
30
+ end
31
+
26
32
  def weight
27
33
  contents.sum(&:weight)
28
34
  end
@@ -2,8 +2,8 @@ module Spree
2
2
  class StockItem < Spree::Base
3
3
  acts_as_paranoid
4
4
 
5
- belongs_to :stock_location, class_name: 'Spree::StockLocation'
6
- belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :stock_items
5
+ belongs_to :stock_location, class_name: 'Spree::StockLocation', inverse_of: :stock_items
6
+ belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :stock_items, counter_cache: true
7
7
  has_many :stock_movements, inverse_of: :stock_item
8
8
 
9
9
  validates_presence_of :stock_location, :variant
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class StockLocation < Spree::Base
3
3
  has_many :shipments
4
- has_many :stock_items, dependent: :delete_all
4
+ has_many :stock_items, dependent: :delete_all, inverse_of: :stock_location
5
5
  has_many :stock_movements, through: :stock_items
6
6
 
7
7
  belongs_to :state, class_name: 'Spree::State'
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Store < Spree::Base
3
3
 
4
- validates :code, presence: true, uniqueness: true
4
+ validates :code, presence: true, uniqueness: { allow_blank: true }
5
5
  validates :name, presence: true
6
6
  validates :url, presence: true
7
7
  validates :mail_from_address, presence: true
@@ -1,9 +1,9 @@
1
1
  module Spree
2
2
  class TaxCategory < Spree::Base
3
3
  acts_as_paranoid
4
- validates :name, presence: true, uniqueness: { scope: :deleted_at }
4
+ validates :name, presence: true, uniqueness: { scope: :deleted_at, allow_blank: true }
5
5
 
6
- has_many :tax_rates, dependent: :destroy
6
+ has_many :tax_rates, dependent: :destroy, inverse_of: :tax_category
7
7
 
8
8
  before_save :set_default_category
9
9
 
@@ -11,10 +11,15 @@ end
11
11
  module Spree
12
12
  class TaxRate < Spree::Base
13
13
  acts_as_paranoid
14
+
15
+ # Need to deal with adjustments before calculator is destroyed.
16
+ before_destroy :deals_with_adjustments_for_deleted_source
17
+
14
18
  include Spree::CalculatedAdjustments
15
19
  include Spree::AdjustmentSource
16
- belongs_to :zone, class_name: "Spree::Zone"
17
- belongs_to :tax_category, class_name: "Spree::TaxCategory"
20
+
21
+ belongs_to :zone, class_name: "Spree::Zone", inverse_of: :tax_rates
22
+ belongs_to :tax_category, class_name: "Spree::TaxCategory", inverse_of: :tax_rates
18
23
 
19
24
  has_many :adjustments, as: :source
20
25
 
@@ -22,8 +27,6 @@ module Spree
22
27
  validates :tax_category_id, presence: true
23
28
  validates_with DefaultTaxZoneValidator
24
29
 
25
- before_destroy :deals_with_adjustments_for_deleted_source
26
-
27
30
  scope :by_zone, ->(zone) { where(zone_id: zone) }
28
31
 
29
32
  # Gets the array of TaxRates appropriate for the specified order
@@ -6,9 +6,14 @@ module Spree
6
6
  has_many :classifications, -> { order(:position) }, dependent: :delete_all, inverse_of: :taxon
7
7
  has_many :products, through: :classifications
8
8
 
9
+ has_and_belongs_to_many :prototypes, join_table: :spree_taxons_prototypes
10
+
9
11
  before_create :set_permalink
10
12
 
11
13
  validates :name, presence: true
14
+ validates :meta_keywords, length: { maximum: 255 }
15
+ validates :meta_description, length: { maximum: 255 }
16
+ validates :meta_title, length: { maximum: 255 }
12
17
 
13
18
  after_touch :touch_ancestors_and_taxonomy
14
19
 
@@ -36,7 +41,7 @@ module Spree
36
41
 
37
42
  # Return meta_title if set otherwise generates from root name and/or taxon name
38
43
  def seo_title
39
- if meta_title
44
+ unless meta_title.blank?
40
45
  meta_title
41
46
  else
42
47
  root? ? name : "#{root.name} - #{name}"
@@ -58,8 +63,7 @@ module Spree
58
63
  end
59
64
 
60
65
  def active_products
61
- scope = products.active
62
- scope
66
+ products.active
63
67
  end
64
68
 
65
69
  def pretty_name