spree_core 2.0.13 → 2.1.0

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