spree_core 3.0.0 → 3.0.1

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