spree_core 2.4.0.rc2 → 2.4.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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