spree_core 3.0.0 → 3.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3affc0ac5855ce03665194985d21e1bf01bcda44
4
- data.tar.gz: ad8218d37fb42edea1f6e34e0554fced3aa4758b
3
+ metadata.gz: 1d168d119d3a44a1239b14adbbbbd73e6fe2d23e
4
+ data.tar.gz: a3fa4208dc96c9d0c279fcd46a579a309faed8de
5
5
  SHA512:
6
- metadata.gz: fac94f550dc92e07f5ecbdefe2151853b8f7963ecf5378bcc61bccc6cb47063792185175041551ff301f810100a4f43873480b0d9d75673f1ad3376532e0ac65
7
- data.tar.gz: 60c7dd641591eaaf0f80bcb48d8fb169fb9e150fe31e87705f3a537a13d107826bb2138ea3019d6f97ba3ebe63c682873a62e3e34e60c3be0b6d58e59e1ca071
6
+ metadata.gz: c968dcf2009be78df09de90f3760f77c945cc86c16d2ca356213defed6699f049fc8823303b737ab6518ce0cec7ff5243d317b8464147e19e90df97dc03d593c
7
+ data.tar.gz: 45a207f6c1c87d87f49d14f0f18798568cb0709ed35f0c8de036c23ef335bf1cb2bbf8046f31ed8b176d452252f7f910f3e1d9f3c7f6d71b4fb6ee2e875b8c07
@@ -3,6 +3,10 @@ class window.Spree
3
3
  @ready: (callback) ->
4
4
  jQuery(document).ready(callback)
5
5
 
6
+ # fire ready callbacks also on turbolinks page change event
7
+ jQuery(document).on 'page:load', ->
8
+ callback(jQuery)
9
+
6
10
  @mountedAt: ->
7
11
  "<%= Rails.application.routes.url_helpers.spree_path %>"
8
12
 
@@ -44,7 +44,7 @@ module Spree
44
44
  end
45
45
 
46
46
  if meta[:description].blank? && object.kind_of?(Spree::Product)
47
- meta[:description] = strip_tags(truncate(object.description, length: 160, separator: ' '))
47
+ meta[:description] = truncate(strip_tags(object.description), length: 160, separator: ' ')
48
48
  end
49
49
 
50
50
  meta.reverse_merge!({
@@ -45,7 +45,7 @@ module Spree
45
45
 
46
46
  def line_item_description_text description_text
47
47
  if description_text.present?
48
- truncate(strip_tags(description_text.gsub('&nbsp;', ' ')), length: 100)
48
+ truncate(strip_tags(description_text.gsub('&nbsp;', ' ').squish), length: 100)
49
49
  else
50
50
  Spree.t(:product_has_no_description)
51
51
  end
@@ -2,7 +2,7 @@ module Spree
2
2
  class Classification < Spree::Base
3
3
  self.table_name = 'spree_products_taxons'
4
4
  acts_as_list scope: :taxon
5
- belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications
5
+ belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications, touch: true
6
6
  belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications, touch: true
7
7
 
8
8
  # For #3494
@@ -24,6 +24,14 @@ module Spree
24
24
  # needed for some of the ActiveMerchant gateways (eg. SagePay)
25
25
  alias_attribute :brand, :cc_type
26
26
 
27
+ # ActiveMerchant::Billing::CreditCard added this accessor used by some gateways.
28
+ # More info: https://github.com/spree/spree/issues/6209
29
+ #
30
+ # Returns or sets the track data for the card
31
+ #
32
+ # @return [String]
33
+ attr_accessor :track_data
34
+
27
35
  CARD_TYPES = {
28
36
  visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
29
37
  master: /(^5[1-5][0-9]{14}$)|(^6759[0-9]{2}([0-9]{10})$)|(^6759[0-9]{2}([0-9]{12})$)|(^6759[0-9]{2}([0-9]{13})$)/,
@@ -3,6 +3,9 @@ require 'spree/order/checkout'
3
3
 
4
4
  module Spree
5
5
  class Order < Spree::Base
6
+ PAYMENT_STATES = %w(balance_due checkout completed credit_owed failed paid pending processing void).freeze
7
+ SHIPMENT_STATES = %w(backorder canceled partial pending ready shipped).freeze
8
+
6
9
  extend FriendlyId
7
10
  friendly_id :number, slug_column: :number, use: :slugged
8
11
 
@@ -277,6 +280,13 @@ module Spree
277
280
  def outstanding_balance
278
281
  if state == 'canceled'
279
282
  -1 * payment_total
283
+ elsif reimbursements.includes(:refunds).size > 0
284
+ reimbursed = reimbursements.includes(:refunds).inject(0) do |sum, reimbursement|
285
+ sum + reimbursement.refunds.sum(:amount)
286
+ end
287
+ # If reimbursement has happened add it back to total to prevent balance_due payment state
288
+ # See: https://github.com/spree/spree/issues/6229
289
+ total - (payment_total + reimbursed)
280
290
  else
281
291
  total - payment_total
282
292
  end
@@ -229,11 +229,11 @@ module Spree
229
229
  success = false
230
230
  @updating_params = params
231
231
  run_callbacks :updating_from_params do
232
- attributes = @updating_params[:order] ? @updating_params[:order].permit(permitted_params).delete_if { |k,v| v.nil? } : {}
233
-
234
232
  # Set existing card after setting permitted parameters because
235
233
  # rails would slice parameters containg ruby objects, apparently
236
- existing_card_id = @updating_params[:order] ? @updating_params[:order][:existing_card] : nil
234
+ existing_card_id = @updating_params[:order] ? @updating_params[:order].delete(:existing_card) : nil
235
+
236
+ attributes = @updating_params[:order] ? @updating_params[:order].permit(permitted_params).delete_if { |k,v| v.nil? } : {}
237
237
 
238
238
  if existing_card_id.present?
239
239
  credit_card = CreditCard.find existing_card_id
@@ -90,7 +90,7 @@ module Spree
90
90
  validates :name, presence: true
91
91
  validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
92
92
  validates :shipping_category_id, presence: true
93
- validates :slug, length: { minimum: 3 }, uniqueness: { allow_blank: true }
93
+ validates :slug, length: { minimum: 3 }, allow_blank: true, uniqueness: true
94
94
 
95
95
  attr_accessor :option_values_hash
96
96
 
@@ -264,7 +264,7 @@ module Spree
264
264
 
265
265
  def punch_slug
266
266
  # punch slug with date prefix to allow reuse of original
267
- update_column :slug, "#{Time.now.to_i}_#{slug}" unless frozen?
267
+ update_column :slug, "#{Time.now.to_i}_#{slug}"[0..254] unless frozen?
268
268
  end
269
269
 
270
270
  def anything_changed?
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ProductProperty < Spree::Base
3
+ acts_as_list scope: :product
4
+
3
5
  belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :product_properties
4
6
  belongs_to :property, class_name: 'Spree::Property', inverse_of: :product_properties
5
7
 
@@ -91,23 +91,28 @@ module Spree
91
91
  # Promotions without rules are eligible by default.
92
92
  return [] if rules.none?
93
93
  eligible = lambda { |r| r.eligible?(promotable, options) }
94
- specific_rules = rules.for(promotable)
94
+ specific_rules = rules.select { |rule| rule.applicable?(promotable) }
95
95
  return [] if specific_rules.none?
96
96
 
97
+ rule_eligibility = Hash[specific_rules.map do |rule|
98
+ [rule, rule.eligible?(promotable, options)]
99
+ end]
100
+
97
101
  if match_all?
98
102
  # If there are rules for this promotion, but no rules for this
99
103
  # particular promotable, then the promotion is ineligible by default.
100
- unless specific_rules.all?(&eligible)
104
+ unless rule_eligibility.values.all?
101
105
  @eligibility_errors = specific_rules.map(&:eligibility_errors).detect(&:present?)
102
106
  return nil
103
107
  end
104
108
  specific_rules
105
109
  else
106
- unless specific_rules.any?(&eligible)
110
+ unless rule_eligibility.values.any?
107
111
  @eligibility_errors = specific_rules.map(&:eligibility_errors).detect(&:present?)
108
112
  return nil
109
113
  end
110
- specific_rules.select(&eligible)
114
+
115
+ [rule_eligibility.detect { |_, eligibility| eligibility }.first]
111
116
  end
112
117
  end
113
118
 
@@ -120,7 +125,8 @@ module Spree
120
125
  end
121
126
 
122
127
  def adjusted_credits_count(promotable)
123
- credits_count - promotable.adjustments.promotion.where(:source_id => actions.pluck(:id)).count
128
+ adjustments = promotable.is_a?(Order) ? promotable.all_adjustments : promotable.adjustments
129
+ credits_count - adjustments.promotion.where(:source_id => actions.pluck(:id)).count
124
130
  end
125
131
 
126
132
  def credits
@@ -39,14 +39,23 @@ module Spree
39
39
  order = options[:order]
40
40
  return unless self.eligible? order
41
41
 
42
+ action_taken = false
42
43
  promotion_action_line_items.each do |item|
43
44
  current_quantity = order.quantity_of(item.variant)
44
- if current_quantity < item.quantity
45
- order.contents.add(item.variant, item.quantity - current_quantity)
45
+ if current_quantity < item.quantity && item_available?(item)
46
+ line_item = order.contents.add(item.variant, item.quantity - current_quantity)
47
+ action_taken = true if line_item.try(:valid?)
46
48
  end
47
49
  end
48
- true
50
+ action_taken
49
51
  end
52
+
53
+ # Checks that there's enough stock to add the line item to the order
54
+ def item_available?(item)
55
+ quantifier = Spree::Stock::Quantifier.new(item.variant)
56
+ quantifier.can_supply? item.quantity
57
+ end
58
+
50
59
  end
51
60
  end
52
61
  end
@@ -79,21 +79,15 @@ module Spree
79
79
  end
80
80
 
81
81
  def determine_promotion_application_result
82
- detector = lambda { |p|
83
- if p.source.promotion.code
84
- p.source.promotion.code.downcase == order.coupon_code.downcase
85
- end
86
- }
87
-
88
82
  # Check for applied adjustments.
89
- discount = order.line_item_adjustments.promotion.detect(&detector)
90
- discount ||= order.shipment_adjustments.promotion.detect(&detector)
91
- discount ||= order.adjustments.promotion.detect(&detector)
83
+ discount = order.all_adjustments.promotion.eligible.detect do |p|
84
+ p.source.promotion.code.try(:downcase) == order.coupon_code.downcase
85
+ end
92
86
 
93
87
  # Check for applied line items.
94
88
  created_line_items = promotion.actions.detect { |a| a.type == 'Spree::Promotion::Actions::CreateLineItems' }
95
89
 
96
- if (discount && discount.eligible) || created_line_items
90
+ if discount || created_line_items
97
91
  order.update_totals
98
92
  order.persist_totals
99
93
  set_success_code :coupon_code_applied
@@ -27,6 +27,8 @@ module Spree
27
27
 
28
28
  before_validation :set_cost_zero_when_nil
29
29
 
30
+ validates :stock_location, presence: true
31
+
30
32
  attr_accessor :special_instructions
31
33
 
32
34
  accepts_nested_attributes_for :address
@@ -87,6 +87,10 @@ module Spree
87
87
  inventory_units: contents.map(&:inventory_unit)
88
88
  )
89
89
  end
90
+
91
+ def contents_by_weight
92
+ contents.sort { |x, y| y.weight <=> x.weight }
93
+ end
90
94
  end
91
95
  end
92
96
  end
@@ -20,8 +20,10 @@ module Spree
20
20
  def reduce(package)
21
21
  removed = []
22
22
  while package.weight > self.threshold
23
- break if package.contents.size == 1
24
- removed << package.contents.shift
23
+ contents = package.contents_by_weight
24
+ break if contents.size == 1
25
+ # Deleting the second heaviest item in the package should yield best results
26
+ removed << package.contents.delete(contents[1])
25
27
  end
26
28
  removed
27
29
  end
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class Variant < Spree::Base
3
3
  acts_as_paranoid
4
+ acts_as_list
4
5
 
5
6
  include Spree::DefaultPrice
6
7
 
@@ -47,6 +48,10 @@ module Spree
47
48
  joins(:prices).where(deleted_at: nil).where('spree_prices.currency' => currency || Spree::Config[:currency]).where('spree_prices.amount IS NOT NULL')
48
49
  end
49
50
 
51
+ def self.having_orders
52
+ joins(:line_items).distinct
53
+ end
54
+
50
55
  def tax_category
51
56
  if self[:tax_category_id].nil?
52
57
  product.tax_category
@@ -172,7 +177,7 @@ module Spree
172
177
  return 0 unless options.present?
173
178
 
174
179
  options.keys.map { |key|
175
- m = "#{options[key]}_price_modifier_amount".to_sym
180
+ m = "#{key}_price_modifier_amount".to_sym
176
181
  if self.respond_to? m
177
182
  self.send(m, options[key])
178
183
  else
@@ -400,7 +400,6 @@ en:
400
400
  add_rule_of_type: Add rule of type
401
401
  add_state: Add State
402
402
  add_stock: Add Stock
403
- add_stock_management: Add Stock Management
404
403
  add_to_cart: Add To Cart
405
404
  add_variant: Add Variant
406
405
  additional_item: Additional Item
@@ -617,7 +616,7 @@ en:
617
616
  discount_amount: Discount Amount
618
617
  dismiss_banner: No. Thanks! I'm not interested, do not display this message again
619
618
  display: Display
620
- doesnt_track_inventory: It doesnt track inventory
619
+ doesnt_track_inventory: It doesn't track inventory
621
620
  edit: Edit
622
621
  editing_resource: 'Editing %{resource}'
623
622
  editing_rma_reason: Editing RMA Reason
@@ -1071,6 +1070,7 @@ en:
1071
1070
  received: Received
1072
1071
  reception_status: Reception Status
1073
1072
  reference: Reference
1073
+ reference_contains: Reference Contains
1074
1074
  refund: Refund
1075
1075
  refund_amount_must_be_greater_than_zero: Refund amount must be greater than zero
1076
1076
  refund_reasons: Refund Reasons
@@ -1,5 +1,12 @@
1
1
  class CreateStoreFromPreferences < ActiveRecord::Migration
2
2
  def change
3
+ # workaround for spree_i18n and Store translations
4
+ Spree::Store.class_eval do
5
+ def self.translated?(name)
6
+ false
7
+ end
8
+ end
9
+
3
10
  preference_store = Spree::Preferences::Store.instance
4
11
  if store = Spree::Store.where(default: true).first
5
12
  store.meta_description = preference_store.get('spree/app_configuration/default_meta_description') {}
@@ -2,7 +2,7 @@ class EnsurePaymentsHaveNumbers < ActiveRecord::Migration
2
2
  def change
3
3
  Spree::Payment.where(number: nil).find_each do |payment|
4
4
  payment.generate_number
5
- payment.save
5
+ payment.update_columns(number: payment.number)
6
6
  end
7
7
  end
8
8
  end
@@ -72,7 +72,7 @@ module Spree
72
72
  if respond_to?(:spree_login_path)
73
73
  redirect_to spree_login_path
74
74
  else
75
- redirect_to spree.respond_to?(:root_path) ? spree.root_path : root_path
75
+ redirect_to spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
76
76
  end
77
77
  end
78
78
  end
@@ -16,9 +16,8 @@ module Spree
16
16
 
17
17
  shipments_attrs = params.delete(:shipments_attributes)
18
18
 
19
- create_shipments_from_params(shipments_attrs, order)
20
19
  create_line_items_from_params(params.delete(:line_items_attributes),order)
21
- create_shipments_from_params(params.delete(:shipments_attributes), order)
20
+ create_shipments_from_params(shipments_attrs, order)
22
21
  create_adjustments_from_params(params.delete(:adjustments_attributes), order)
23
22
  create_payments_from_params(params.delete(:payments_attributes), order)
24
23
 
@@ -50,44 +49,45 @@ module Spree
50
49
  def self.create_shipments_from_params(shipments_hash, order)
51
50
  return [] unless shipments_hash
52
51
 
53
- line_items = order.line_items
52
+ inventory_units = Spree::Stock::InventoryUnitBuilder.new(order).units
53
+
54
54
  shipments_hash.each do |s|
55
55
  begin
56
56
  shipment = order.shipments.build
57
57
  shipment.tracking = s[:tracking]
58
58
  shipment.stock_location = Spree::StockLocation.find_by_admin_name(s[:stock_location]) || Spree::StockLocation.find_by_name!(s[:stock_location])
59
59
 
60
- inventory_units = s[:inventory_units] || []
61
- inventory_units.each do |iu|
62
- ensure_variant_id_from_params(iu)
63
-
64
- unit = shipment.inventory_units.build
65
- unit.order = order
66
-
67
- # Spree expects a Inventory Unit to always reference a line
68
- # item and variant otherwise users might get exceptions when
69
- # trying to view these units. Note the Importer might not be
70
- # able to find the line item if line_item.variant_id |= iu.variant_id
71
- unit.variant_id = iu[:variant_id]
72
- unit.line_item_id = line_items.select do |l|
73
- l.variant_id.to_i == iu[:variant_id].to_i
74
- end.first.try(:id)
60
+ shipment_units = s[:inventory_units] || []
61
+ shipment_units.each do |su|
62
+ ensure_variant_id_from_params(su)
63
+
64
+ inventory_unit = inventory_units.detect { |iu| iu.variant_id.to_i == su[:variant_id].to_i }
65
+
66
+ if inventory_unit.present?
67
+ inventory_unit.shipment = shipment
68
+
69
+ if s[:shipped_at].present?
70
+ inventory_unit.pending = false
71
+ inventory_unit.state = 'shipped'
72
+ end
73
+
74
+ inventory_unit.save!
75
+
76
+ # Don't assign shipments to this inventory unit more than once
77
+ inventory_units.delete(inventory_unit)
78
+ end
75
79
  end
76
80
 
77
- # Mark shipped if it should be.
78
81
  if s[:shipped_at].present?
79
82
  shipment.shipped_at = s[:shipped_at]
80
83
  shipment.state = 'shipped'
81
- shipment.inventory_units.each do |unit|
82
- unit.state = 'shipped'
83
- end
84
84
  end
85
85
 
86
86
  shipment.save!
87
87
 
88
88
  shipping_method = Spree::ShippingMethod.find_by_name(s[:shipping_method]) || Spree::ShippingMethod.find_by_admin_name!(s[:shipping_method])
89
- rate = shipment.shipping_rates.create!(:shipping_method => shipping_method,
90
- :cost => s[:cost])
89
+ rate = shipment.shipping_rates.create!(shipping_method: shipping_method, cost: s[:cost])
90
+
91
91
  shipment.selected_shipping_rate_id = rate.id
92
92
  shipment.update_amounts
93
93
 
@@ -192,6 +192,7 @@ module Spree
192
192
  # Order API should be using state as that's the normal payment field.
193
193
  # spree_wombat serializes payment state as status so imported orders should fall back to status field.
194
194
  payment.state = p[:state] || p[:status] || 'completed'
195
+ payment.created_at = p[:created_at] if p[:created_at]
195
196
  payment.payment_method = Spree::PaymentMethod.find_by_name!(p[:payment_method])
196
197
  payment.source = create_source_payment_from_params(p[:source], payment) if p[:source]
197
198
  payment.save!
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  def self.version
3
- "3.0.0"
3
+ "3.0.1"
4
4
  end
5
5
  end
@@ -61,7 +61,9 @@ module Spree
61
61
  :meta_keywords, :price, :sku, :deleted_at, :prototype_id,
62
62
  :option_values_hash, :weight, :height, :width, :depth,
63
63
  :shipping_category_id, :tax_category_id,
64
- :taxon_ids, :option_type_ids, :cost_currency, :cost_price]
64
+ :taxon_ids, :cost_currency, :cost_price,
65
+ option_type_ids: []
66
+ ]
65
67
 
66
68
  @@property_attributes = [:name, :presentation]
67
69
 
@@ -101,8 +103,10 @@ module Spree
101
103
 
102
104
  @@variant_attributes = [
103
105
  :name, :presentation, :cost_price, :lock_version,
104
- :position, :option_value_ids, :track_inventory,
106
+ :position, :track_inventory,
105
107
  :product_id, :product, :option_values_attributes, :price,
106
- :weight, :height, :width, :depth, :sku, :cost_currency, options: [ :name, :value ]]
108
+ :weight, :height, :width, :depth, :sku, :cost_currency,
109
+ options: [:name, :value], option_value_ids: []
110
+ ]
107
111
  end
108
112
  end
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :image, class: Spree::Image do
3
+ attachment { File.new(Spree::Core::Engine.root + "spec/fixtures" + 'thinking-cat.jpg') }
4
+ end
5
+ end
data/lib/tasks/email.rake CHANGED
@@ -1,9 +1,9 @@
1
1
  namespace :email do
2
- desc 'Sends test email to specified address - Example: EMAIL=spree@example.com bundle exec rake test:email'
2
+ desc 'Sends test email to specified address - Example: EMAIL=spree@example.com bundle exec rake email:test'
3
3
  task test: :environment do
4
4
  unless ENV['EMAIL'].present?
5
5
  raise ArgumentError, "Must pass EMAIL environment variable. " \
6
- "Example: EMAIL=spree@example.com bundle exec rake test:email"
6
+ "Example: EMAIL=spree@example.com bundle exec rake email:test"
7
7
  end
8
8
  Spree::TestMailer.test_email(ENV['EMAIL']).deliver_now
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Schofield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-10 00:00:00.000000000 Z
11
+ date: 2015-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.46.0
19
+ version: 1.47.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.46.0
26
+ version: 1.47.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: acts_as_list
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -842,6 +842,7 @@ files:
842
842
  - lib/spree/testing_support/factories/country_factory.rb
843
843
  - lib/spree/testing_support/factories/credit_card_factory.rb
844
844
  - lib/spree/testing_support/factories/customer_return_factory.rb
845
+ - lib/spree/testing_support/factories/image_factory.rb
845
846
  - lib/spree/testing_support/factories/inventory_unit_factory.rb
846
847
  - lib/spree/testing_support/factories/line_item_factory.rb
847
848
  - lib/spree/testing_support/factories/options_factory.rb