spree_core 2.0.13 → 2.1.0

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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/base_controller.rb +3 -0
  3. data/app/helpers/spree/base_helper.rb +6 -16
  4. data/app/helpers/spree/products_helper.rb +3 -8
  5. data/app/helpers/spree/taxons_helper.rb +1 -1
  6. data/app/mailers/spree/base_mailer.rb +0 -5
  7. data/app/models/spree/ability.rb +10 -7
  8. data/app/models/spree/address.rb +7 -17
  9. data/app/models/spree/adjustment.rb +15 -11
  10. data/app/models/spree/app_configuration.rb +0 -5
  11. data/app/models/spree/billing_integration.rb +0 -1
  12. data/app/models/spree/calculator/flat_percent_item_total.rb +1 -3
  13. data/app/models/spree/calculator/flat_rate.rb +2 -4
  14. data/app/models/spree/calculator/flexi_rate.rb +6 -9
  15. data/app/models/spree/calculator/per_item.rb +2 -4
  16. data/app/models/spree/calculator/percent_per_item.rb +1 -3
  17. data/app/models/spree/calculator/price_sack.rb +4 -9
  18. data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +1 -2
  19. data/app/models/spree/calculator/shipping/flat_rate.rb +2 -4
  20. data/app/models/spree/calculator/shipping/flexi_rate.rb +4 -9
  21. data/app/models/spree/calculator/shipping/per_item.rb +2 -3
  22. data/app/models/spree/calculator/shipping/price_sack.rb +4 -9
  23. data/app/models/spree/classification.rb +0 -3
  24. data/app/models/spree/country.rb +1 -3
  25. data/app/models/spree/credit_card.rb +37 -38
  26. data/app/models/spree/gateway/bogus_simple.rb +0 -8
  27. data/app/models/spree/gateway.rb +1 -3
  28. data/app/models/spree/image.rb +1 -3
  29. data/app/models/spree/inventory_unit.rb +5 -8
  30. data/app/models/spree/legacy_user.rb +0 -4
  31. data/app/models/spree/line_item.rb +2 -15
  32. data/app/models/spree/option_type.rb +2 -5
  33. data/app/models/spree/option_value.rb +1 -3
  34. data/app/models/spree/order/checkout.rb +4 -13
  35. data/app/models/spree/order.rb +47 -99
  36. data/app/models/spree/order_contents.rb +4 -7
  37. data/app/models/spree/order_inventory.rb +4 -8
  38. data/app/models/spree/order_updater.rb +13 -12
  39. data/app/models/spree/payment/processing.rb +12 -19
  40. data/app/models/spree/payment.rb +17 -30
  41. data/app/models/spree/payment_method.rb +2 -3
  42. data/app/models/spree/preference.rb +1 -1
  43. data/app/models/spree/preferences/configuration.rb +1 -1
  44. data/app/models/spree/preferences/preferable.rb +1 -1
  45. data/app/models/spree/preferences/store.rb +1 -1
  46. data/app/models/spree/price.rb +0 -7
  47. data/app/models/spree/product/scopes.rb +16 -17
  48. data/app/models/spree/product.rb +27 -62
  49. data/app/models/spree/product_property.rb +3 -5
  50. data/app/models/spree/promotion/actions/create_adjustment.rb +9 -8
  51. data/app/models/spree/promotion/actions/create_line_items.rb +1 -2
  52. data/app/models/spree/promotion/rules/first_order.rb +1 -1
  53. data/app/models/spree/promotion/rules/item_total.rb +2 -4
  54. data/app/models/spree/promotion/rules/product.rb +2 -2
  55. data/app/models/spree/promotion/rules/user.rb +1 -3
  56. data/app/models/spree/promotion.rb +23 -24
  57. data/app/models/spree/promotion_action.rb +0 -2
  58. data/app/models/spree/promotion_action_line_item.rb +1 -3
  59. data/app/models/spree/promotion_rule.rb +0 -2
  60. data/app/models/spree/property.rb +2 -4
  61. data/app/models/spree/prototype.rb +0 -2
  62. data/app/models/spree/return_authorization.rb +6 -9
  63. data/app/models/spree/role.rb +0 -2
  64. data/app/models/spree/shipment.rb +19 -25
  65. data/app/models/spree/shipping_calculator.rb +0 -2
  66. data/app/models/spree/shipping_category.rb +0 -2
  67. data/app/models/spree/shipping_method.rb +6 -20
  68. data/app/models/spree/shipping_rate.rb +12 -10
  69. data/app/models/spree/state.rb +2 -4
  70. data/app/models/spree/stock/availability_validator.rb +2 -2
  71. data/app/models/spree/stock/estimator.rb +6 -20
  72. data/app/models/spree/stock/packer.rb +1 -1
  73. data/app/models/spree/stock/quantifier.rb +2 -3
  74. data/app/models/spree/stock/splitter/base.rb +1 -1
  75. data/app/models/spree/stock_item.rb +8 -18
  76. data/app/models/spree/stock_location.rb +2 -11
  77. data/app/models/spree/stock_movement.rb +2 -5
  78. data/app/models/spree/stock_transfer.rb +0 -2
  79. data/app/models/spree/tax_category.rb +0 -2
  80. data/app/models/spree/tax_rate.rb +12 -12
  81. data/app/models/spree/taxon.rb +1 -13
  82. data/app/models/spree/taxonomy.rb +3 -6
  83. data/app/models/spree/tracker.rb +0 -2
  84. data/app/models/spree/variant/scopes.rb +2 -2
  85. data/app/models/spree/variant.rb +13 -31
  86. data/app/models/spree/zone.rb +2 -7
  87. data/app/models/spree/zone_member.rb +0 -2
  88. data/app/views/spree/payments/_payment.html.erb +1 -3
  89. data/config/locales/en.yml +11 -26
  90. data/db/default/spree/countries.rb +230 -229
  91. data/db/default/spree/states.rb +57 -56
  92. data/db/default/spree/zones.rb +5 -5
  93. data/db/migrate/20130213191427_create_default_stock.rb +4 -7
  94. data/db/migrate/20130417120035_update_adjustment_states.rb +2 -2
  95. data/db/migrate/20130417123427_add_shipping_rates_to_shipments.rb +1 -1
  96. data/db/migrate/20130509115210_add_number_to_stock_transfer.rb +1 -1
  97. data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +0 -5
  98. data/db/migrate/20130611185927_add_user_id_index_to_spree_orders.rb +5 -0
  99. data/db/migrate/20130618041418_add_updated_at_to_spree_countries.rb +9 -0
  100. data/db/migrate/20130619012236_add_updated_at_to_spree_states.rb +9 -0
  101. data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +4 -5
  102. data/db/migrate/20130806145853_set_default_stock_location_on_shipments.rb +1 -1
  103. data/lib/generators/spree/dummy/dummy_generator.rb +3 -14
  104. data/lib/generators/spree/dummy/templates/rails/database.yml +0 -10
  105. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -7
  106. data/lib/generators/spree/install/install_generator.rb +11 -8
  107. data/lib/spree/core/calculated_adjustments.rb +9 -8
  108. data/lib/spree/core/controller_helpers/auth.rb +2 -3
  109. data/lib/spree/core/controller_helpers/order.rb +8 -13
  110. data/lib/spree/core/controller_helpers/ssl.rb +13 -22
  111. data/lib/spree/core/controller_helpers/strong_parameters.rb +36 -0
  112. data/lib/spree/core/delegate_belongs_to.rb +0 -2
  113. data/lib/spree/core/engine.rb +1 -5
  114. data/lib/spree/core/ext/active_record.rb +2 -9
  115. data/lib/spree/core/permalinks.rb +1 -5
  116. data/lib/spree/core/product_duplicator.rb +2 -16
  117. data/lib/spree/core/product_filters.rb +37 -33
  118. data/lib/spree/core/search/base.rb +1 -1
  119. data/lib/spree/core/version.rb +1 -1
  120. data/lib/spree/core.rb +3 -31
  121. data/lib/spree/i18n.rb +0 -1
  122. data/lib/spree/money.rb +2 -177
  123. data/lib/spree/permitted_attributes.rb +95 -0
  124. data/lib/spree/promo/coupon_applicator.rb +4 -12
  125. data/lib/spree/testing_support/capybara_ext.rb +13 -17
  126. data/lib/spree/testing_support/common_rake.rb +1 -1
  127. data/lib/spree/testing_support/controller_requests.rb +3 -3
  128. data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
  129. data/lib/spree/testing_support/factories/product_factory.rb +0 -4
  130. data/lib/spree/testing_support/factories/shipping_method_factory.rb +1 -3
  131. data/lib/spree/testing_support/factories/user_factory.rb +1 -1
  132. data/lib/spree/testing_support/factories/variant_factory.rb +0 -15
  133. data/lib/spree/testing_support/factories.rb +1 -1
  134. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  135. data/lib/tasks/core.rake +2 -2
  136. data/vendor/assets/javascripts/jquery.payment.js +497 -0
  137. metadata +166 -172
  138. data/app/views/spree/admin/shared/_report_order_criteria.html.erb +0 -17
  139. data/db/migrate/20130417120034_add_index_to_source_columns_on_adjustments.rb +0 -5
  140. data/db/migrate/20130830001033_add_shipping_category_to_shipping_methods_and_products.rb +0 -15
  141. data/db/migrate/20130830001159_migrate_old_shipping_calculators.rb +0 -19
  142. data/db/migrate/20130909115621_change_states_required_for_countries.rb +0 -9
  143. data/db/migrate/20131001013410_remove_unused_credit_card_fields.rb +0 -12
  144. data/db/migrate/20131026154747_add_track_inventory_to_variant.rb +0 -5
  145. data/db/migrate/20131113035136_add_channel_to_spree_orders.rb +0 -5
  146. data/db/migrate/20140120160805_add_index_to_variant_id_and_currency_on_prices.rb +0 -5
  147. data/db/migrate/20140205181631_default_variant_weight_to_zero.rb +0 -11
  148. data/db/migrate/20140415041315_add_user_id_created_by_id_index_to_order.rb +0 -5
  149. data/lib/spree/core/preference_rescue.rb +0 -25
@@ -37,8 +37,6 @@ module DelegateBelongsTo
37
37
  attrs = get_association_column_names(association) if attrs.empty?
38
38
  attrs.concat get_association_column_names(association) if attrs.delete :defaults
39
39
  attrs.each do |attr|
40
- next if attribute_method?(attr)
41
-
42
40
  class_def attr do |*args|
43
41
  if args.empty?
44
42
  send(:delegator_for, association).send(attr)
@@ -86,11 +86,7 @@ module Spree
86
86
  ]
87
87
  end
88
88
 
89
- # Promotion rules need to be evaluated on after initialize otherwise
90
- # Spree.user_class would be nil and users might experience errors related
91
- # to malformed model associations (Spree.user_class is only defined on
92
- # the app initializer)
93
- config.after_initialize do
89
+ initializer 'spree.promo.register.promotion.calculators' do
94
90
  Rails.application.config.spree.promotions.rules.concat [
95
91
  Spree::Promotion::Rules::ItemTotal,
96
92
  Spree::Promotion::Rules::Product,
@@ -2,14 +2,7 @@ module ActiveRecord::Persistence
2
2
 
3
3
  # Update attributes of a record in the database without callbacks, validations etc.
4
4
  def update_attributes_without_callbacks(attributes)
5
- self.assign_attributes(attributes, :without_protection => true)
6
- self.class.update_all(attributes, { :id => id })
5
+ self.assign_attributes(attributes)
6
+ self.class.where(:id => id).update_all(attributes)
7
7
  end
8
-
9
- # Update a single attribute in the database
10
- def update_attribute_without_callbacks(name, value)
11
- send("#{name}=", value)
12
- update_attributes_without_callbacks(name => value)
13
- end
14
-
15
8
  end
@@ -37,10 +37,6 @@ module Spree
37
37
  permalink_options[:prefix] || ""
38
38
  end
39
39
 
40
- def permalink_length
41
- permalink_options[:length] || 9
42
- end
43
-
44
40
  def permalink_order
45
41
  order = permalink_options[:order]
46
42
  "#{order} ASC," if order
@@ -48,7 +44,7 @@ module Spree
48
44
  end
49
45
 
50
46
  def generate_permalink
51
- "#{self.class.permalink_prefix}#{Array.new(self.class.permalink_length){rand(9)}.join}"
47
+ "#{self.class.permalink_prefix}#{Array.new(9){rand(9)}.join}"
52
48
  end
53
49
 
54
50
  def save_permalink(permalink_value=self.to_param)
@@ -2,12 +2,8 @@ module Spree
2
2
  class ProductDuplicator
3
3
  attr_accessor :product
4
4
 
5
- @@clone_images_default = true
6
- mattr_accessor :clone_images_default
7
-
8
- def initialize(product, include_images = @@clone_images_default)
5
+ def initialize(product)
9
6
  @product = product
10
- @include_images = include_images
11
7
  end
12
8
 
13
9
  def duplicate
@@ -27,14 +23,12 @@ module Spree
27
23
  def duplicate_product
28
24
  product.dup.tap do |new_product|
29
25
  new_product.name = "COPY OF #{product.name}"
30
- new_product.permalink = "copy-of-#{product.permalink}"
31
26
  new_product.taxons = product.taxons
32
27
  new_product.created_at = nil
33
28
  new_product.deleted_at = nil
34
29
  new_product.updated_at = nil
35
30
  new_product.product_properties = reset_properties
36
31
  new_product.master = duplicate_master
37
- new_product.variants = product.variants.map { |variant| duplicate_variant variant }
38
32
  end
39
33
  end
40
34
 
@@ -43,20 +37,12 @@ module Spree
43
37
  master.dup.tap do |new_master|
44
38
  new_master.sku = "COPY OF #{master.sku}"
45
39
  new_master.deleted_at = nil
46
- new_master.images = master.images.map { |image| duplicate_image image } if @include_images
40
+ new_master.images = master.images.map { |image| duplicate_image image }
47
41
  new_master.price = master.price
48
42
  new_master.currency = master.currency
49
43
  end
50
44
  end
51
45
 
52
- def duplicate_variant(variant)
53
- new_variant = variant.dup
54
- new_variant.sku = "COPY OF #{new_variant.sku}"
55
- new_variant.deleted_at = nil
56
- new_variant.option_values = variant.option_values.map { |option_value| option_value}
57
- new_variant
58
- end
59
-
60
46
  def duplicate_image(image)
61
47
  new_image = image.dup
62
48
  new_image.assign_attributes(:attachment => image.attachment.clone)
@@ -57,12 +57,12 @@ module Spree
57
57
  # below scope would be something like ["$10 - $15", "$15 - $18", "$18 - $20"]
58
58
  #
59
59
  Spree::Product.add_search_scope :price_range_any do |*opts|
60
- conds = opts.map {|o| Spree::Core::ProductFilters.price_filter[:conds][o]}.reject {|c| c.nil?}
60
+ conds = opts.map {|o| Spree::Core::ProductFilters.price_filter[:conds][o]}.reject { |c| c.nil? }
61
61
  scope = conds.shift
62
62
  conds.each do |new_scope|
63
63
  scope = scope.or(new_scope)
64
64
  end
65
- Spree::Product.joins(:master => :default_price).where(scope)
65
+ Spree::Product.joins(master: :default_price).where(scope)
66
66
  end
67
67
 
68
68
  def ProductFilters.format_price(amount)
@@ -71,15 +71,16 @@ module Spree
71
71
 
72
72
  def ProductFilters.price_filter
73
73
  v = Spree::Price.arel_table
74
- conds = [ [ Spree.t(:under_price, :price => format_price(10)) , v[:amount].lteq(10)],
74
+ conds = [ [ Spree.t(:under_price, price: format_price(10)) , v[:amount].lteq(10)],
75
75
  [ "#{format_price(10)} - #{format_price(15)}" , v[:amount].in(10..15)],
76
76
  [ "#{format_price(15)} - #{format_price(18)}" , v[:amount].in(15..18)],
77
77
  [ "#{format_price(18)} - #{format_price(20)}" , v[:amount].in(18..20)],
78
- [ Spree.t(:or_over_price, :price => format_price(20)) , v[:amount].gteq(20)]]
79
- { :name => Spree.t(:price_range),
80
- :scope => :price_range_any,
81
- :conds => Hash[*conds.flatten],
82
- :labels => conds.map {|k,v| [k,k]}
78
+ [ Spree.t(:or_over_price, price: format_price(20)) , v[:amount].gteq(20)]]
79
+ {
80
+ name: Spree.t(:price_range),
81
+ scope: :price_range_any,
82
+ conds: Hash[*conds.flatten],
83
+ labels: conds.map { |k,v| [k, k] }
83
84
  }
84
85
  end
85
86
 
@@ -98,23 +99,24 @@ module Spree
98
99
  # rather than an inner join.
99
100
  if Spree::Property.table_exists?
100
101
  Spree::Product.add_search_scope :brand_any do |*opts|
101
- conds = opts.map {|o| ProductFilters.brand_filter[:conds][o]}.reject {|c| c.nil?}
102
+ conds = opts.map {|o| ProductFilters.brand_filter[:conds][o]}.reject { |c| c.nil? }
102
103
  scope = conds.shift
103
104
  conds.each do |new_scope|
104
105
  scope = scope.or(new_scope)
105
106
  end
106
- Spree::Product.with_property("brand").where(scope)
107
+ Spree::Product.with_property('brand').where(scope)
107
108
  end
108
109
 
109
110
  def ProductFilters.brand_filter
110
- brand_property = Spree::Property.find_by_name("brand")
111
- brands = Spree::ProductProperty.where(:property_id => brand_property).pluck(:value).uniq.map(&:to_s)
111
+ brand_property = Spree::Property.find_by(name: 'brand')
112
+ brands = brand_property ? Spree::ProductProperty.where(property_id: brand_property.id).pluck(:value).uniq.map(&:to_s) : []
112
113
  pp = Spree::ProductProperty.arel_table
113
114
  conds = Hash[*brands.map { |b| [b, pp[:value].eq(b)] }.flatten]
114
- { :name => "Brands",
115
- :scope => :brand_any,
116
- :conds => conds,
117
- :labels => (brands.sort).map { |k| [k, k] }
115
+ {
116
+ name: 'Brands',
117
+ scope: :brand_any,
118
+ conds: conds,
119
+ labels: (brands.sort).map { |k| [k, k] }
118
120
  }
119
121
  end
120
122
  end
@@ -145,16 +147,16 @@ module Spree
145
147
 
146
148
  def ProductFilters.selective_brand_filter(taxon = nil)
147
149
  taxon ||= Spree::Taxonomy.first.root
148
- brand_property = Spree::Property.find_by_name("brand")
149
- scope = Spree::ProductProperty.where(:property_id => brand_property).
150
- joins(:product => :taxons).
151
- where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants).
152
- scoped
150
+ brand_property = Spree::Property.find_by(name: 'brand')
151
+ scope = Spree::ProductProperty.where(property: brand_property).
152
+ joins(product: :taxons).
153
+ where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants).
154
+ scoped
153
155
  brands = scope.pluck(:value).uniq
154
156
  {
155
- :name => "Applicable Brands",
156
- :scope => :selective_brand_any,
157
- :labels => brands.sort.map { |k| [k,k] }
157
+ name: 'Applicable Brands',
158
+ scope: :selective_brand_any,
159
+ labels: brands.sort.map { |k| [k, k] }
158
160
  }
159
161
  end
160
162
  end
@@ -173,10 +175,11 @@ module Spree
173
175
  #
174
176
  def ProductFilters.taxons_below(taxon)
175
177
  return Spree::Core::ProductFilters.all_taxons if taxon.nil?
176
- { :name => "Taxons under " + taxon.name,
177
- :scope => :taxons_id_in_tree_any,
178
- :labels => taxon.children.sort_by(&:position).map {|t| [t.name, t.id]},
179
- :conds => nil
178
+ {
179
+ name: 'Taxons under ' + taxon.name,
180
+ scope: :taxons_id_in_tree_any,
181
+ labels: taxon.children.sort_by(&:position).map { |t| [t.name, t.id] },
182
+ conds: nil
180
183
  }
181
184
  end
182
185
 
@@ -187,11 +190,12 @@ module Spree
187
190
  #
188
191
  # idea: expand the format to allow nesting of labels?
189
192
  def ProductFilters.all_taxons
190
- taxons = Spree::Taxonomy.all.map {|t| [t.root] + t.root.descendants }.flatten
191
- { :name => "All taxons",
192
- :scope => :taxons_id_equals_any,
193
- :labels => taxons.sort_by(&:name).map {|t| [t.name, t.id]},
194
- :conds => nil # not needed
193
+ taxons = Spree::Taxonomy.all.map { |t| [t.root] + t.root.descendants }.flatten
194
+ {
195
+ name: 'All taxons',
196
+ scope: :taxons_id_equals_any,
197
+ labels: taxons.sort_by(&:name).map { |t| [t.name, t.id] },
198
+ conds: nil # not needed
195
199
  }
196
200
  end
197
201
  end
@@ -46,7 +46,7 @@ module Spree
46
46
  if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
47
47
  base_scope = base_scope.send(scope_name, *scope_attribute)
48
48
  else
49
- base_scope = base_scope.merge(Spree::Product.search({scope_name => scope_attribute}).result)
49
+ base_scope = base_scope.merge(Spree::Product.ransack({scope_name => scope_attribute}).result)
50
50
  end
51
51
  end if search
52
52
  base_scope
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  def self.version
3
- '2.0.13'
3
+ "2.1.0"
4
4
  end
5
5
  end
data/lib/spree/core.rb CHANGED
@@ -5,7 +5,6 @@ require 'awesome_nested_set'
5
5
  require 'cancan'
6
6
  require 'kaminari'
7
7
  require 'mail'
8
- require 'monetize'
9
8
  require 'paperclip'
10
9
  require 'paranoia'
11
10
  require 'ransack'
@@ -17,9 +16,9 @@ module Spree
17
16
 
18
17
  def self.user_class
19
18
  if @@user_class.is_a?(Class)
20
- raise "Spree.user_class MUST be a String or Symbol object, not a Class object."
21
- elsif @@user_class.is_a?(String) || @@user_class.is_a?(Symbol)
22
- @@user_class.to_s.constantize
19
+ raise "Spree.user_class MUST be a String object, not a Class object."
20
+ elsif @@user_class.is_a?(String)
21
+ @@user_class.constantize
23
22
  end
24
23
  end
25
24
 
@@ -55,30 +54,3 @@ require 'spree/core/product_duplicator'
55
54
  ActiveRecord::Base.class_eval do
56
55
  include CollectiveIdea::Acts::NestedSet
57
56
  end
58
-
59
- # Monkey patch to give us miliseconds precision in timestamps
60
- module ActiveSupport
61
- class TimeWithZone
62
- # Coerces time to a string for JSON encoding. The default format is ISO 8601. You can get
63
- # %Y/%m/%d %H:%M:%S +offset style by setting <tt>ActiveSupport::JSON::Encoding.use_standard_json_time_format</tt>
64
- # to false.
65
- #
66
- # ==== Examples
67
- #
68
- # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
69
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
70
- # # => "2005-02-01T15:15:10.001Z"
71
- #
72
- # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
73
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
74
- # # => "2005/02/01 15:15:10 +0000"
75
- #
76
- def as_json(options = nil)
77
- if ActiveSupport::JSON::Encoding.use_standard_json_time_format
78
- xmlschema(3)
79
- else
80
- %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
81
- end
82
- end
83
- end
84
- end
data/lib/spree/i18n.rb CHANGED
@@ -4,7 +4,6 @@ require 'spree/i18n/base'
4
4
 
5
5
  module Spree
6
6
  extend ActionView::Helpers::TranslationHelper
7
- extend ActionView::Helpers::TagHelper
8
7
 
9
8
  class << self
10
9
  # Add spree namespace and delegate to Rails TranslationHelper for some nice
data/lib/spree/money.rb CHANGED
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'money'
4
2
 
5
3
  module Spree
@@ -9,187 +7,18 @@ module Spree
9
7
  delegate :cents, :to => :money
10
8
 
11
9
  def initialize(amount, options={})
12
- @money = self.class.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
10
+ @money = ::Money.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
13
11
  @options = {}
14
12
  @options[:with_currency] = Spree::Config[:display_currency]
15
13
  @options[:symbol_position] = Spree::Config[:currency_symbol_position].to_sym
16
14
  @options[:no_cents] = Spree::Config[:hide_cents]
17
15
  @options[:decimal_mark] = Spree::Config[:currency_decimal_mark]
18
16
  @options[:thousands_separator] = Spree::Config[:currency_thousands_separator]
19
- @options[:sign_before_symbol] = Spree::Config[:currency_sign_before_symbol]
20
17
  @options.merge!(options)
21
18
  # Must be a symbol because the Money gem doesn't do the conversion
22
19
  @options[:symbol_position] = @options[:symbol_position].to_sym
23
20
  end
24
21
 
25
- # This method is being deprecated in Money 6.1.0, so now lives here.
26
- def self.parse(input, currency = nil)
27
- i = input.to_s.strip
28
-
29
- # raise Money::Currency.table.collect{|c| c[1][:symbol]}.inspect
30
-
31
- # Check the first character for a currency symbol, alternatively get it
32
- # from the stated currency string
33
- c = if ::Monetize.assume_from_symbol && i =~ /^(\$|€|£)/
34
- case i
35
- when /^\$/ then "USD"
36
- when /^€/ then "EUR"
37
- when /^£/ then "GBP"
38
- end
39
- else
40
- i[/[A-Z]{2,3}/]
41
- end
42
-
43
- # check that currency passed and embedded currency are the same,
44
- # and negotiate the final currency
45
- if currency.nil? and c.nil?
46
- currency = ::Money.default_currency
47
- elsif currency.nil?
48
- currency = c
49
- elsif c.nil?
50
- currency = currency
51
- elsif currency != c
52
- # TODO: ParseError
53
- raise ArgumentError, "Mismatching Currencies"
54
- end
55
- currency = ::Money::Currency.wrap(currency)
56
-
57
- fractional = extract_cents(i, currency)
58
- ::Money.new(fractional, currency)
59
- end
60
-
61
- # This method is being deprecated in Money 6.1.0, so now lives here.
62
- def self.extract_cents(input, currency = Money.default_currency)
63
- # remove anything that's not a number, potential thousands_separator, or minus sign
64
- num = input.gsub(/[^\d.,'-]/, '')
65
-
66
- # set a boolean flag for if the number is negative or not
67
- negative = num =~ /^-|-$/ ? true : false
68
-
69
- # decimal mark character
70
- decimal_char = currency.decimal_mark
71
-
72
- # if negative, remove the minus sign from the number
73
- # if it's not negative, the hyphen makes the value invalid
74
- if negative
75
- num = num.sub(/^-|-$/, '')
76
- end
77
-
78
- raise ArgumentError, "Invalid currency amount (hyphen)" if num.include?('-')
79
-
80
- #if the number ends with punctuation, just throw it out. If it means decimal,
81
- #it won't hurt anything. If it means a literal period or comma, this will
82
- #save it from being mis-interpreted as a decimal.
83
- num.chop! if num.match(/[\.|,]$/)
84
-
85
- # gather all decimal_marks within the result number
86
- used_delimiters = num.scan(/[^\d]/)
87
-
88
- # determine the number of unique decimal_marks within the number
89
- #
90
- # e.g.
91
- # $1,234,567.89 would return 2 (, and .)
92
- # $125,00 would return 1
93
- # $199 would return 0
94
- # $1 234,567.89 would raise an error (decimal_marks are space, comma, and period)
95
- case used_delimiters.uniq.length
96
- # no decimal_mark or thousands_separator; major (dollars) is the number, and minor (cents) is 0
97
- when 0 then major, minor = num, 0
98
-
99
- # two decimal_marks, so we know the last item in this array is the
100
- # major/minor thousands_separator and the rest are decimal_marks
101
- when 2
102
- thousands_separator, decimal_mark = used_delimiters.uniq
103
-
104
- # remove all thousands_separator, split on the decimal_mark
105
- major, minor = num.gsub(thousands_separator, '').split(decimal_mark)
106
- min = 0 unless min
107
- when 1
108
- # we can't determine if the comma or period is supposed to be a decimal_mark or a thousands_separator
109
- # e.g.
110
- # 1,00 - comma is a thousands_separator
111
- # 1.000 - period is a thousands_separator
112
- # 1,000 - comma is a decimal_mark
113
- # 1,000,000 - comma is a decimal_mark
114
- # 10000,00 - comma is a thousands_separator
115
- # 1000,000 - comma is a thousands_separator
116
-
117
- # assign first decimal_mark for reusability
118
- decimal_mark = used_delimiters.first
119
-
120
- # When we have identified the decimal mark character
121
- if decimal_char == decimal_mark
122
- major, minor = num.split(decimal_char)
123
-
124
- else
125
- # decimal_mark is used as a decimal_mark when there are multiple instances, always
126
- if num.scan(decimal_mark).length > 1 # multiple matches; treat as decimal_mark
127
- major, minor = num.gsub(decimal_mark, ''), 0
128
- else
129
- # ex: 1,000 - 1.0000 - 10001.000
130
- # split number into possible major (dollars) and minor (cents) values
131
- possible_major, possible_minor = num.split(decimal_mark)
132
- possible_major ||= "0"
133
- possible_minor ||= "00"
134
-
135
- # if the minor (cents) length isn't 3, assign major/minor from the possibles
136
- # e.g.
137
- # 1,00 => 1.00
138
- # 1.0000 => 1.00
139
- # 1.2 => 1.20
140
- if possible_minor.length != 3 # thousands_separator
141
- major, minor = possible_major, possible_minor
142
- else
143
- # minor length is three
144
- # let's try to figure out intent of the thousands_separator
145
-
146
- # the major length is greater than three, which means
147
- # the comma or period is used as a thousands_separator
148
- # e.g.
149
- # 1000,000
150
- # 100000,000
151
- if possible_major.length > 3
152
- major, minor = possible_major, possible_minor
153
- else
154
- # number is in format ###{sep}### or ##{sep}### or #{sep}###
155
- # handle as , is sep, . is thousands_separator
156
- if decimal_mark == '.'
157
- major, minor = possible_major, possible_minor
158
- else
159
- major, minor = "#{possible_major}#{possible_minor}", 0
160
- end
161
- end
162
- end
163
- end
164
- end
165
- else
166
- # TODO: ParseError
167
- raise ArgumentError, "Invalid currency amount"
168
- end
169
-
170
- # build the string based on major/minor since decimal_mark/thousands_separator have been removed
171
- # avoiding floating point arithmetic here to ensure accuracy
172
- cents = (major.to_i * currency.subunit_to_unit)
173
- # Because of an bug in JRuby, we can't just call #floor
174
- minor = minor.to_s
175
- minor = if minor.size < currency.decimal_places
176
- (minor + ("0" * currency.decimal_places))[0,currency.decimal_places].to_i
177
- elsif minor.size > currency.decimal_places
178
- if minor[currency.decimal_places,1].to_i >= 5
179
- minor[0,currency.decimal_places].to_i+1
180
- else
181
- minor[0,currency.decimal_places].to_i
182
- end
183
- else
184
- minor.to_i
185
- end
186
-
187
- cents += minor
188
-
189
- # if negative, multiply by -1; otherwise, return positive cents
190
- negative ? cents * -1 : cents
191
- end
192
-
193
22
  def to_s
194
23
  @money.format(@options)
195
24
  end
@@ -199,15 +28,11 @@ module Spree
199
28
  if options[:html]
200
29
  # 1) prevent blank, breaking spaces
201
30
  # 2) prevent escaping of HTML character entities
202
- output = output.sub(" ", "&nbsp;").html_safe
31
+ output = output.gsub(" ", "&nbsp;").html_safe
203
32
  end
204
33
  output
205
34
  end
206
35
 
207
- def as_json(*)
208
- to_s
209
- end
210
-
211
36
  def ==(obj)
212
37
  @money == obj.money
213
38
  end
@@ -0,0 +1,95 @@
1
+ module Spree
2
+ module PermittedAttributes
3
+ ATTRIBUTES = [
4
+ :address_attributes,
5
+ :checkout_attributes,
6
+ :image_attributes,
7
+ :inventory_unit_attributes,
8
+ :line_item_attributes,
9
+ :option_type_attributes,
10
+ :option_value_attributes,
11
+ :payment_attributes,
12
+ :product_attributes,
13
+ :product_properties_attributes,
14
+ :property_attributes,
15
+ :return_authorization_attributes,
16
+ :shipment_attributes,
17
+ :source_attributes,
18
+ :stock_item_attributes,
19
+ :stock_location_attributes,
20
+ :stock_movement_attributes,
21
+ :taxon_attributes,
22
+ :taxonomy_attributes,
23
+ :user_attributes,
24
+ :variant_attributes
25
+ ]
26
+
27
+ mattr_reader *ATTRIBUTES
28
+
29
+ @@address_attributes = [
30
+ :firstname, :lastname, :address1, :address2,
31
+ :city, :country_id, :state_id, :zipcode, :phone,
32
+ :state_name, :alternative_phone, :company]
33
+
34
+ @@checkout_attributes = [:email, :use_billing, :shipping_method_id, :coupon_code]
35
+
36
+ @@image_attributes = [:alt, :attachment, :position, :viewable_type, :viewable_id]
37
+
38
+ @@inventory_unit_attributes = [:shipment, :variant_id]
39
+
40
+ @@line_item_attributes = [:id, :variant_id, :quantity]
41
+
42
+ @@option_type_attributes = [:name, :presentation, :option_values_attributes]
43
+
44
+ @@option_value_attributes = [:name, :presentation]
45
+
46
+ @@payment_attributes = [:amount, :payment_method_id]
47
+
48
+ @@product_properties_attributes = [:property_name, :value, :position]
49
+
50
+ @@product_attributes = [
51
+ :name, :description, :available_on, :permalink, :meta_description,
52
+ :meta_keywords, :price, :sku, :deleted_at, :prototype_id,
53
+ :option_values_hash, :weight, :height, :width, :depth,
54
+ :shipping_category_id, :tax_category_id, :product_properties_attributes,
55
+ :variants_attributes, :taxon_ids, :option_type_ids, :cost_currency, :cost_price]
56
+
57
+ @@property_attributes = [:name, :presentation]
58
+
59
+ @@return_authorization_attributes = [:amount, :reason, :stock_location_id]
60
+
61
+ @@shipment_attributes = [
62
+ :order, :special_instructions, :stock_location_id, :id,
63
+ :tracking, :address, :inventory_units, :selected_shipping_rate_id]
64
+
65
+ # month / year may be provided by some sources, or others may elect to use one field
66
+ @@source_attributes = [
67
+ :number, :month, :year, :expiry, :verification_value,
68
+ :first_name, :last_name, :cc_type]
69
+
70
+ @@stock_item_attributes = [:variant, :stock_location, :backorderable, :variant_id]
71
+
72
+ @@stock_location_attributes = [
73
+ :name, :active, :address1, :address2, :city, :zipcode,
74
+ :backorderable_default, :state_name, :state_id, :country_id, :phone,
75
+ :propagate_all_variants]
76
+
77
+ @@stock_movement_attributes = [
78
+ :quantity, :stock_item, :stock_item_id, :originator, :action]
79
+
80
+ @@taxonomy_attributes = [:name]
81
+
82
+ @@taxon_attributes = [
83
+ :name, :parent_id, :position, :icon, :description, :permalink, :taxonomy_id,
84
+ :meta_description, :meta_keywords, :meta_title]
85
+
86
+ # TODO Should probably use something like Spree.user_class.attributes
87
+ @@user_attributes = [:email, :password, :password_confirmation]
88
+
89
+ @@variant_attributes = [
90
+ :name, :presentation, :cost_price, :lock_version,
91
+ :position, :option_value_ids,
92
+ :product_id, :option_values_attributes, :price,
93
+ :weight, :height, :width, :depth, :sku, :cost_currency]
94
+ end
95
+ end
@@ -13,7 +13,7 @@ module Spree
13
13
  if @order.adjustments.promotion.eligible.detect { |p| p.originator.promotion.code == @order.coupon_code }.present?
14
14
  return { :coupon_applied? => true, :notice => Spree.t(:coupon_code_already_applied) }
15
15
  else
16
- promotion = Spree::Promotion.find_by_code(@order.coupon_code)
16
+ promotion = Spree::Promotion.find_by(code: @order.coupon_code)
17
17
  if promotion.present?
18
18
  handle_present_promotion(promotion)
19
19
  else
@@ -32,17 +32,9 @@ module Spree
32
32
  return promotion_usage_limit_exceeded if promotion.usage_limit_exceeded?
33
33
 
34
34
  event_name = "spree.checkout.coupon_code_added"
35
- if promotion.activate(:coupon_code => @order.coupon_code, :order => @order)
36
- promo = @order.adjustments.includes(:originator).promotion.detect { |p| p.originator.promotion.code == @order.coupon_code }
37
- if promo.present?
38
- determine_promotion_application_result(promo)
39
- else
40
- # if action is create line items
41
- return { :coupon_applied? => true, :success => Spree.t(:coupon_code_applied) }
42
- end
43
- else
44
- return { :coupon_applied? => false, :error => Spree.t(:coupon_code_not_eligible) }
45
- end
35
+ promotion.activate(:coupon_code => @order.coupon_code, :order => @order)
36
+ promo = @order.adjustments.includes(:originator).promotion.detect { |p| p.originator.promotion.code == @order.coupon_code }
37
+ determine_promotion_application_result(promo)
46
38
  end
47
39
 
48
40
  def promotion_expired