spree_core 2.3.4 → 2.3.5

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +1 -1
  3. data/app/helpers/spree/products_helper.rb +7 -8
  4. data/app/models/spree/adjustment.rb +3 -1
  5. data/app/models/spree/asset.rb +1 -1
  6. data/app/models/spree/classification.rb +1 -1
  7. data/app/models/spree/credit_card.rb +2 -2
  8. data/app/models/spree/gateway/bogus.rb +3 -2
  9. data/app/models/spree/inventory_unit.rb +1 -1
  10. data/app/models/spree/item_adjustments.rb +8 -4
  11. data/app/models/spree/line_item.rb +5 -0
  12. data/app/models/spree/order.rb +8 -4
  13. data/app/models/spree/order/checkout.rb +2 -0
  14. data/app/models/spree/payment.rb +6 -3
  15. data/app/models/spree/payment_method.rb +7 -3
  16. data/app/models/spree/payment_method/check.rb +2 -0
  17. data/app/models/spree/price.rb +1 -13
  18. data/app/models/spree/product.rb +26 -24
  19. data/app/models/spree/promotion.rb +2 -2
  20. data/app/models/spree/promotion/actions/create_item_adjustments.rb +5 -3
  21. data/app/models/spree/promotion/actions/create_line_items.rb +1 -0
  22. data/app/models/spree/promotion_handler/coupon.rb +5 -1
  23. data/app/models/spree/return_authorization.rb +2 -2
  24. data/app/models/spree/shipping_category.rb +2 -2
  25. data/app/models/spree/shipping_method_category.rb +1 -1
  26. data/app/models/spree/stock_item.rb +1 -1
  27. data/app/models/spree/stock_location.rb +1 -1
  28. data/app/models/spree/store.rb +1 -1
  29. data/app/models/spree/tax_category.rb +2 -2
  30. data/app/models/spree/tax_rate.rb +7 -4
  31. data/app/models/spree/variant.rb +18 -17
  32. data/app/models/spree/zone.rb +15 -17
  33. data/app/models/spree/zone_member.rb +1 -1
  34. data/config/initializers/user_class_extensions.rb +10 -9
  35. data/config/locales/en.yml +4 -1
  36. data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +1 -1
  37. data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +3 -5
  38. data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +5 -0
  39. data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +13 -0
  40. data/db/migrate/20141105213646_update_classifications_positions.rb +9 -0
  41. data/lib/generators/spree/install/install_generator.rb +3 -7
  42. data/lib/spree/core.rb +3 -3
  43. data/lib/spree/core/controller_helpers/order.rb +8 -7
  44. data/lib/spree/core/importer/order.rb +16 -3
  45. data/lib/spree/core/search/base.rb +1 -1
  46. data/lib/spree/core/validators/email.rb +1 -1
  47. data/lib/spree/core/version.rb +1 -1
  48. data/lib/spree/localized_number.rb +20 -0
  49. data/lib/spree/migrations.rb +7 -3
  50. data/lib/spree/money.rb +2 -2
  51. data/lib/spree/permitted_attributes.rb +3 -1
  52. data/lib/spree/testing_support/ability_helpers.rb +25 -25
  53. data/lib/spree/testing_support/capybara_ext.rb +2 -2
  54. data/lib/spree/testing_support/factories/line_item_factory.rb +1 -1
  55. data/lib/spree/testing_support/factories/order_factory.rb +1 -1
  56. data/lib/spree/testing_support/factories/promotion_factory.rb +4 -4
  57. data/lib/spree/testing_support/factories/stock_factory.rb +2 -2
  58. data/lib/spree/testing_support/flash.rb +2 -2
  59. metadata +16 -19
  60. data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +0 -23
  61. data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +0 -25
  62. data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +0 -25
  63. data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +0 -25
  64. data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +0 -25
  65. data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +0 -25
  66. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +0 -26
  67. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +0 -26
  68. data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +0 -25
  69. data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +0 -23
  70. data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +0 -25
  71. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +0 -25
  72. 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: cf31759b42f3d9c77f519a0a834197545d65fe4d
4
- data.tar.gz: e2950f378e975c121125d09ffb62aec3ecd97378
3
+ metadata.gz: 2b6ba75da732715ef975c684a089a3586b67cec1
4
+ data.tar.gz: 4afbf2136510cb63bab7f1b60e2192c03a10a48c
5
5
  SHA512:
6
- metadata.gz: 4e41ee0be0df3a866211bc0c9b96fa1cfe803317f1c0b286d1c8d241e639eff8afd5886a78a55c5b3ee6dd38cc8601c5957898b07cf0cfd65070d66804243b60
7
- data.tar.gz: 6bb17dd15d7e92b168eaba7f5d6b662a193a6739125ff3a7ee33ff08a76979924b463964b791b67e8d79e8f3c4e5de1bf694ab0e4bcaae9b9835b6da272c3f33
6
+ metadata.gz: 33a1fe7fdb7080cac31739ec3202a51d3d6e6ffb1da1bf80ea76688ac796b2a545326eba10f6773fcd1d80bbcc57a7abe0353fa610df2daeeab3209bad473f8d
7
+ data.tar.gz: 2a9c302304140f816e3f1236790b147de50d96b1816e91208a2808b7ad9818ac426d389d53a6b4b978f3d86b888728d2cf7125f46cce75486ce7d7d2c391de46
@@ -48,7 +48,7 @@ module Spree
48
48
  meta.reverse_merge!({
49
49
  keywords: current_store.meta_keywords,
50
50
  description: current_store.meta_description,
51
- })
51
+ }) if meta[:keywords].blank? or meta[:description].blank?
52
52
  meta
53
53
  end
54
54
 
@@ -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
 
@@ -101,7 +103,7 @@ module Spree
101
103
 
102
104
  def update_adjustable_adjustment_total
103
105
  # Cause adjustable's total to be recalculated
104
- Spree::ItemAdjustments.new(adjustable).update if adjustable
106
+ ItemAdjustments.new(adjustable).update
105
107
  end
106
108
 
107
109
  end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Asset < Spree::Base
3
3
  belongs_to :viewable, polymorphic: true, touch: true
4
- acts_as_list scope: :viewable
4
+ acts_as_list scope: [:viewable_id, :viewable_type]
5
5
  end
6
6
  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
 
@@ -132,8 +132,8 @@ module Spree
132
132
  if month.to_i < 1 || month.to_i > 12
133
133
  errors.add(:base, :expiry_invalid)
134
134
  else
135
- time = Time.zone.parse("#{year}-#{month}-1")
136
- if time < Time.zone.now.to_time.beginning_of_month
135
+ current = Time.current
136
+ if year.to_i < current.year or (year.to_i == current.year and month.to_i < current.month)
137
137
  errors.add(:base, :card_expired)
138
138
  end
139
139
  end
@@ -19,8 +19,9 @@ module Spree
19
19
 
20
20
  def create_profile(payment)
21
21
  # simulate the storage of credit card profile using remote service
22
- success = VALID_CCS.include? payment.source.number
23
- payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
22
+ if success = VALID_CCS.include?(payment.source.number)
23
+ payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
24
+ end
24
25
  end
25
26
 
26
27
  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
  scope :backordered, -> { where state: 'backordered' }
@@ -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; effecting 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
@@ -72,7 +76,7 @@ module Spree
72
76
  end
73
77
 
74
78
  def best_promotion_adjustment
75
- @best_promotion_adjustment ||= adjustments.promotion.eligible.reorder("amount ASC, created_at DESC").first
79
+ @best_promotion_adjustment ||= adjustments.promotion.eligible.reorder("amount ASC, created_at DESC, id DESC").first
76
80
  end
77
81
  end
78
82
  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
@@ -102,6 +103,10 @@ module Spree
102
103
  end
103
104
  end
104
105
 
106
+ def destroy_inventory_units
107
+ inventory_units.destroy_all
108
+ end
109
+
105
110
  def update_adjustments
106
111
  if quantity_changed?
107
112
  update_tax_charge # Called to ensure pre_tax_amount is updated.
@@ -37,9 +37,9 @@ module Spree
37
37
  alias_attribute :ship_total, :shipment_total
38
38
 
39
39
  has_many :state_changes, as: :stateful
40
- has_many :line_items, -> { order('created_at ASC') }, dependent: :destroy, inverse_of: :order
40
+ has_many :line_items, -> { order("#{LineItem.table_name}.created_at ASC") }, dependent: :destroy, inverse_of: :order
41
41
  has_many :payments, dependent: :destroy
42
- has_many :return_authorizations, dependent: :destroy
42
+ has_many :return_authorizations, dependent: :destroy, inverse_of: :order
43
43
  has_many :adjustments, -> { order("#{Adjustment.table_name}.created_at ASC") }, as: :adjustable, dependent: :destroy
44
44
  has_many :line_item_adjustments, through: :line_items, source: :adjustments
45
45
  has_many :shipment_adjustments, through: :shipments, source: :adjustments
@@ -74,7 +74,7 @@ module Spree
74
74
 
75
75
  validates :email, presence: true, if: :require_email
76
76
  validates :email, email: true, if: :require_email, allow_blank: true
77
- validates :number, uniqueness: true
77
+ validates :number, presence: true, uniqueness: { allow_blank: true }
78
78
  validate :has_available_shipment
79
79
 
80
80
  make_permalink field: :number
@@ -415,7 +415,11 @@ module Spree
415
415
 
416
416
  def ensure_line_items_are_in_stock
417
417
  if insufficient_stock_lines.present?
418
- errors.add(:base, Spree.t(:insufficient_stock_lines_present)) and return false
418
+ errors.add(:base, Spree.t(:insufficient_stock_lines_present))
419
+ restart_checkout_flow
420
+ false
421
+ else
422
+ true
419
423
  end
420
424
  end
421
425
 
@@ -102,6 +102,8 @@ module Spree
102
102
 
103
103
  before_transition to: :resumed, do: :ensure_line_items_are_in_stock
104
104
 
105
+ before_transition to: :complete, do: :ensure_line_items_are_in_stock
106
+
105
107
  after_transition to: :complete, do: :finalize!
106
108
  after_transition to: :resumed, do: :after_resume
107
109
  after_transition to: :canceled, do: :after_cancel
@@ -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, -> { where("source_type = 'Spree::Payment' AND amount < 0 AND state = 'completed'") },
14
14
  class_name: "Spree::Payment", foreign_key: :source_id
@@ -175,6 +175,7 @@ module Spree
175
175
 
176
176
  def create_payment_profile
177
177
  return unless source.respond_to?(:has_payment_profile?) && !source.has_payment_profile?
178
+ return if %w(invalid failed).include?(state)
178
179
  # Imported payments shouldn't create a payment profile.
179
180
  return if source.imported
180
181
 
@@ -184,8 +185,10 @@ module Spree
184
185
  end
185
186
 
186
187
  def invalidate_old_payments
187
- order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
188
- payment.invalidate!
188
+ if state != 'invalid' and state != 'failed'
189
+ order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
190
+ payment.invalidate!
191
+ end
189
192
  end
190
193
  end
191
194
 
@@ -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
@@ -16,14 +16,14 @@ module Spree
16
16
  end
17
17
 
18
18
  def provider_class
19
- raise 'You must implement provider_class method for this gateway.'
19
+ raise ::NotImplementedError, 'You must implement provider_class method for this gateway.'
20
20
  end
21
21
 
22
22
  # The class that will process payments for this payment type, used for @payment.source
23
23
  # e.g. CreditCard in the case of a the Gateway payment type
24
24
  # nil means the payment method doesn't require a source e.g. check
25
25
  def payment_source_class
26
- raise 'You must implement payment_source_class method for this gateway.'
26
+ raise ::NotImplementedError, 'You must implement payment_source_class method for this gateway.'
27
27
  end
28
28
 
29
29
  def self.available(display_on = 'both')
@@ -67,5 +67,9 @@ module Spree
67
67
  def supports?(source)
68
68
  true
69
69
  end
70
+
71
+ def cancel(response)
72
+ raise ::NotImplementedError, 'You must implement cancel method for this payment method.'
73
+ end
70
74
  end
71
75
  end
@@ -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
@@ -21,7 +21,7 @@ module Spree
21
21
  end
22
22
 
23
23
  def price=(price)
24
- self[:amount] = parse_price(price)
24
+ self[:amount] = Spree::LocalizedNumber.parse(price)
25
25
  end
26
26
 
27
27
  # Remove variant default_scope `deleted_at: nil`
@@ -39,18 +39,6 @@ module Spree
39
39
  end
40
40
  end
41
41
 
42
- # strips all non-price-like characters from the price, taking into account locale settings
43
- def parse_price(price)
44
- return price unless price.is_a?(String)
45
-
46
- separator, delimiter = I18n.t([:'number.currency.format.separator', :'number.currency.format.delimiter'])
47
- non_price_characters = /[^0-9\-#{separator}]/
48
- price.gsub!(non_price_characters, '') # strip everything else first
49
- price.gsub!(separator, '.') unless separator == '.' # then replace the locale-specific decimal separator with the standard separator if necessary
50
-
51
- price.to_d
52
- end
53
-
54
42
  def maximum_amount
55
43
  BigDecimal '999999.99'
56
44
  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
 
@@ -65,29 +64,32 @@ module Spree
65
64
 
66
65
  delegate_belongs_to :master, :cost_price
67
66
 
67
+ delegate :images, to: :master, prefix: true
68
+ alias_method :images, :master_images
69
+
70
+ has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
71
+
68
72
  after_create :set_master_variant_defaults
69
73
  after_create :add_properties_and_option_types_from_prototype
70
74
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
71
75
 
76
+ after_destroy :punch_slug
77
+
78
+ after_initialize :ensure_master
79
+
72
80
  after_save :save_master
73
81
  after_save :run_touch_callbacks, if: :anything_changed?
74
82
  after_save :reset_nested_changes
75
83
  after_touch :touch_taxons
76
84
 
77
- delegate :images, to: :master, prefix: true
78
- alias_method :images, :master_images
79
-
80
- has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
85
+ before_validation :normalize_slug, on: :update
86
+ before_validation :validate_master
81
87
 
88
+ validates :meta_keywords, length: { maximum: 255 }
82
89
  validates :name, presence: true
83
90
  validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
84
91
  validates :shipping_category_id, presence: true
85
- validates :slug, length: { minimum: 3 }
86
- validates :slug, uniqueness: true
87
-
88
- before_validation :normalize_slug, on: :update
89
-
90
- after_destroy :punch_slug
92
+ validates :slug, length: { minimum: 3 }, uniqueness: { allow_blank: true }
91
93
 
92
94
  attr_accessor :option_values_hash
93
95
 
@@ -95,8 +97,6 @@ module Spree
95
97
 
96
98
  alias :options :product_option_types
97
99
 
98
- after_initialize :ensure_master
99
-
100
100
  # the master variant is not a member of the variants array
101
101
  def has_variants?
102
102
  variants.any?
@@ -276,19 +276,21 @@ module Spree
276
276
  # when saving so we force a save using a hook
277
277
  # Fix for issue #5306
278
278
  def save_master
279
- begin
280
- if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
281
- master.save!
282
- @nested_changes = true
283
- end
279
+ if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
280
+ master.save!
281
+ @nested_changes = true
282
+ end
283
+ end
284
284
 
285
- # If the master cannot be saved, the Product object will get its errors
286
- # and will be destroyed
287
- rescue ActiveRecord::RecordInvalid
285
+ # If the master cannot be saved, the Product object will get its errors
286
+ # and will be destroyed
287
+ def validate_master
288
+ # We call master.default_price here to ensure price is initialized.
289
+ # Required to avoid Variant#check_price validation failing on create.
290
+ unless master.default_price && master.valid?
288
291
  master.errors.each do |att, error|
289
292
  self.errors.add(att, error)
290
293
  end
291
- raise
292
294
  end
293
295
  end
294
296
 
@@ -16,7 +16,7 @@ module Spree
16
16
  validates_associated :rules
17
17
 
18
18
  validates :name, presence: true
19
- validates :path, uniqueness: true, allow_blank: true
19
+ validates :path, uniqueness: { allow_blank: true }
20
20
  validates :usage_limit, numericality: { greater_than: 0, allow_nil: true }
21
21
  validates :description, length: { maximum: 255 }
22
22
 
@@ -30,7 +30,7 @@ module Spree
30
30
  end
31
31
 
32
32
  def self.with_coupon_code(coupon_code)
33
- where("lower(code) = ?", coupon_code.strip.downcase).first
33
+ where("lower(#{self.table_name}.code) = ?", coupon_code.strip.downcase).first
34
34
  end
35
35
 
36
36
  def self.active
@@ -14,10 +14,12 @@ module Spree
14
14
 
15
15
  def perform(payload = {})
16
16
  order = payload[:order]
17
- # Find only the line items which have not already been adjusted by this promotion
17
+ # Find only the orders' line items which have not already been adjusted by this promotion
18
18
  # HACK: Need to use [0] because `pluck` may return an empty array, which AR helpfully
19
19
  # coverts to meaning NOT IN (NULL) and the DB isn't happy about that.
20
- already_adjusted_line_items = [0] + self.adjustments.pluck(:adjustable_id)
20
+ already_adjusted_line_items = [0] + self.adjustments.
21
+ where(adjustable_id: order.line_items.pluck(:id), adjustable_type: 'Spree::LineItem').
22
+ pluck(:adjustable_id)
21
23
  result = false
22
24
  order.line_items.where("id NOT IN (?)", already_adjusted_line_items).find_each do |line_item|
23
25
  current_result = self.create_adjustment(line_item, order)
@@ -43,7 +45,7 @@ module Spree
43
45
  # item_total and ship_total
44
46
  def compute_amount(adjustable)
45
47
  promotion_amount = self.calculator.compute(adjustable).to_f.abs
46
-
48
+
47
49
  [adjustable.amount, promotion_amount].min * -1
48
50
  end
49
51