spree_core 2.4.10 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/app/assets/images/logo/spree_50.png +0 -0
  4. data/app/controllers/spree/base_controller.rb +1 -2
  5. data/app/helpers/spree/base_helper.rb +41 -131
  6. data/app/helpers/spree/products_helper.rb +1 -1
  7. data/app/models/concerns/spree/adjustment_source.rb +51 -15
  8. data/app/models/concerns/spree/calculated_adjustments.rb +1 -0
  9. data/app/models/concerns/spree/display_money.rb +32 -0
  10. data/app/models/concerns/spree/named_type.rb +1 -1
  11. data/app/models/concerns/spree/number_generator.rb +39 -0
  12. data/app/models/concerns/spree/user_reporting.rb +3 -8
  13. data/app/models/spree/address.rb +0 -2
  14. data/app/models/spree/adjustable/adjustments_updater.rb +70 -0
  15. data/app/models/spree/adjustable/promotion_accumulator.rb +75 -0
  16. data/app/models/spree/adjustment.rb +17 -26
  17. data/app/models/spree/app_configuration.rb +4 -33
  18. data/app/models/spree/base.rb +0 -3
  19. data/app/models/spree/calculator.rb +0 -5
  20. data/app/models/spree/classification.rb +1 -1
  21. data/app/models/spree/country.rb +10 -4
  22. data/app/models/spree/credit_card.rb +14 -15
  23. data/app/models/spree/customer_return.rb +18 -25
  24. data/app/models/spree/gateway/bogus.rb +0 -4
  25. data/app/models/spree/line_item.rb +2 -5
  26. data/app/models/spree/option_type.rb +2 -4
  27. data/app/models/spree/option_value.rb +0 -2
  28. data/app/models/spree/order.rb +74 -134
  29. data/app/models/spree/order/checkout.rb +1 -1
  30. data/app/models/spree/order_contents.rb +9 -8
  31. data/app/models/spree/order_updater.rb +8 -1
  32. data/app/models/spree/payment.rb +13 -23
  33. data/app/models/spree/payment/gateway_options.rb +86 -0
  34. data/app/models/spree/payment/processing.rb +8 -39
  35. data/app/models/spree/payment_method.rb +3 -6
  36. data/app/models/spree/price.rb +2 -6
  37. data/app/models/spree/product.rb +27 -16
  38. data/app/models/spree/product_property.rb +1 -5
  39. data/app/models/spree/promotion.rb +7 -15
  40. data/app/models/spree/promotion/actions/create_adjustment.rb +4 -45
  41. data/app/models/spree/promotion/actions/create_item_adjustments.rb +8 -63
  42. data/app/models/spree/promotion/actions/create_line_items.rb +3 -12
  43. data/app/models/spree/promotion/actions/free_shipping.rb +4 -24
  44. data/app/models/spree/promotion/rules/option_value.rb +49 -0
  45. data/app/models/spree/promotion_action.rb +6 -0
  46. data/app/models/spree/promotion_handler/cart.rb +14 -18
  47. data/app/models/spree/promotion_handler/coupon.rb +1 -1
  48. data/app/models/spree/promotion_rule.rb +0 -1
  49. data/app/models/spree/property.rb +0 -2
  50. data/app/models/spree/refund.rb +0 -15
  51. data/app/models/spree/reimbursement.rb +4 -4
  52. data/app/models/spree/reimbursement_type/credit.rb +1 -1
  53. data/app/models/spree/reimbursement_type/original_payment.rb +1 -1
  54. data/app/models/spree/return_authorization.rb +4 -11
  55. data/app/models/spree/return_item.rb +16 -11
  56. data/app/models/spree/return_item/eligibility_validator/default.rb +2 -0
  57. data/app/models/spree/return_item/eligibility_validator/inventory_shipped.rb +16 -0
  58. data/app/models/spree/return_item/eligibility_validator/no_reimbursements.rb +16 -0
  59. data/app/models/spree/shipment.rb +20 -31
  60. data/app/models/spree/shipment_handler.rb +1 -1
  61. data/app/models/spree/shipping_method.rb +12 -13
  62. data/app/models/spree/state.rb +7 -0
  63. data/app/models/spree/state_change.rb +1 -6
  64. data/app/models/spree/stock/availability_validator.rb +9 -10
  65. data/app/models/spree/stock/coordinator.rb +1 -1
  66. data/app/models/spree/stock/estimator.rb +6 -6
  67. data/app/models/spree/stock/quantifier.rb +1 -1
  68. data/app/models/spree/stock_item.rb +1 -7
  69. data/app/models/spree/stock_location.rb +3 -1
  70. data/app/models/spree/stock_movement.rb +1 -8
  71. data/app/models/spree/stock_transfer.rb +11 -5
  72. data/app/models/spree/store.rb +2 -2
  73. data/app/models/spree/tax_rate.rb +30 -55
  74. data/app/models/spree/taxon.rb +8 -8
  75. data/app/models/spree/taxonomy.rb +8 -13
  76. data/app/models/spree/tracker.rb +1 -1
  77. data/app/models/spree/variant.rb +6 -15
  78. data/app/models/spree/zone.rb +43 -9
  79. data/config/initializers/user_class_extensions.rb +0 -12
  80. data/config/locales/en.yml +76 -85
  81. data/config/routes.rb +1 -1
  82. data/db/default/spree/countries.rb +23 -13
  83. data/db/default/spree/states.rb +24 -12
  84. data/db/default/spree/stores.rb +1 -1
  85. data/db/migrate/20120831092320_spree_one_two.rb +36 -36
  86. data/db/migrate/20120831092359_spree_promo_one_two.rb +1 -1
  87. data/db/migrate/20130211190146_create_spree_stock_items.rb +1 -1
  88. data/db/migrate/20130211191120_create_spree_stock_locations.rb +1 -1
  89. data/db/migrate/20130301162924_create_shipping_method_categories.rb +1 -1
  90. data/db/migrate/20130304162240_create_spree_shipping_rates.rb +1 -1
  91. data/db/migrate/20130305143310_create_stock_movements.rb +1 -1
  92. data/db/migrate/20130418125341_create_spree_stock_transfers.rb +1 -1
  93. data/db/migrate/20140205120320_create_spree_payment_capture_events.rb +1 -1
  94. data/db/migrate/20140309024355_create_spree_stores.rb +1 -1
  95. data/db/migrate/20140309033438_create_store_from_preferences.rb +0 -7
  96. data/db/migrate/20140625214618_create_spree_refunds.rb +1 -1
  97. data/db/migrate/20140702140656_create_spree_return_authorization_inventory_unit.rb +1 -1
  98. data/db/migrate/20140713140455_create_spree_return_authorization_reasons.rb +1 -1
  99. data/db/migrate/20140713140527_create_spree_refund_reasons.rb +1 -1
  100. data/db/migrate/20140715182625_create_spree_promotion_categories.rb +1 -1
  101. data/db/migrate/20140718133010_create_spree_customer_returns.rb +1 -1
  102. data/db/migrate/20140725131539_create_spree_reimbursements.rb +1 -1
  103. data/db/migrate/20140731150017_create_spree_reimbursement_types.rb +1 -1
  104. data/db/migrate/20140911173301_add_kind_to_zone.rb +11 -0
  105. data/db/migrate/20141215232040_remove_token_permissions_table.rb +6 -0
  106. data/db/migrate/20141215235502_remove_extra_products_slug_index.rb +5 -0
  107. data/db/migrate/20141217215630_update_product_slug_index.rb +6 -0
  108. data/db/migrate/20141218025915_rename_identifier_to_number_for_payment.rb +5 -0
  109. data/db/migrate/20150121022521_remove_environment_from_payment_method.rb +6 -0
  110. data/db/migrate/20150122145607_add_resellable_to_return_items.rb +5 -0
  111. data/db/migrate/20150122202432_add_code_to_spree_promotion_categories.rb +5 -0
  112. data/db/migrate/20150128032538_remove_environment_from_tracker.rb +6 -0
  113. data/db/migrate/20150128060325_remove_spree_configurations.rb +16 -0
  114. data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
  115. data/lib/generators/spree/install/templates/config/initializers/spree.rb +4 -0
  116. data/lib/spree/core.rb +2 -12
  117. data/lib/spree/core/controller_helpers/respond_with.rb +8 -18
  118. data/lib/spree/core/engine.rb +1 -7
  119. data/lib/spree/core/routes.rb +1 -1
  120. data/lib/spree/core/version.rb +1 -1
  121. data/lib/spree/money.rb +10 -10
  122. data/lib/spree/permitted_attributes.rb +4 -8
  123. data/lib/spree/testing_support/authorization_helpers.rb +3 -5
  124. data/lib/spree/testing_support/capybara_ext.rb +3 -3
  125. data/lib/spree/testing_support/common_rake.rb +2 -2
  126. data/lib/spree/testing_support/factories/order_factory.rb +3 -13
  127. data/lib/spree/testing_support/factories/payment_method_factory.rb +0 -3
  128. data/lib/spree/testing_support/factories/prototype_factory.rb +5 -0
  129. data/lib/spree/testing_support/factories/return_item_factory.rb +5 -1
  130. data/lib/spree/testing_support/factories/stock_location_factory.rb +3 -3
  131. data/lib/spree/testing_support/factories/tracker_factory.rb +0 -1
  132. data/lib/spree/testing_support/factories/user_factory.rb +1 -1
  133. data/lib/spree/testing_support/factories/zone_factory.rb +8 -0
  134. data/lib/tasks/core.rake +1 -1
  135. data/lib/tasks/email.rake +6 -3
  136. metadata +48 -35
  137. data/app/helpers/spree/checkout_helper.rb +0 -31
  138. data/app/helpers/spree/orders_helper.rb +0 -17
  139. data/app/helpers/spree/store_helper.rb +0 -16
  140. data/app/helpers/spree/taxons_helper.rb +0 -19
  141. data/app/models/concerns/spree/ransackable_attributes.rb +0 -19
  142. data/app/models/friendly_id/slug_decorator.rb +0 -3
  143. data/app/models/spree/billing_integration.rb +0 -21
  144. data/app/models/spree/configuration.rb +0 -5
  145. data/app/models/spree/item_adjustments.rb +0 -82
  146. data/app/models/spree/order_merger.rb +0 -65
  147. data/app/models/spree/order_populator.rb +0 -43
  148. data/app/models/spree/product_scope/scopes.rb +0 -47
  149. data/app/models/spree/variant/scopes.rb +0 -42
  150. data/db/migrate/20150515211137_fix_adjustment_order_id.rb +0 -70
  151. data/db/migrate/20150522181728_add_deleted_at_to_friendly_id_slugs.rb +0 -6
  152. data/db/migrate/20150707204155_enable_acts_as_paranoid_on_calculators.rb +0 -6
  153. data/lib/spree/core/controller_helpers/ssl.rb +0 -60
  154. data/lib/spree/core/permalinks.rb +0 -71
  155. data/lib/spree/testing_support/factories/configuration_factory.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 920d1116f3ab6e3411d25cbb20a68d9a3219dc54
4
- data.tar.gz: 5ce011d689d7dc2c8b5daa7af24fa35cda922a75
3
+ metadata.gz: 599174c8bcc4c415e7a65af40048eeff77e07147
4
+ data.tar.gz: f0b4346703e8ff979bc55c7ba86204e5878d163c
5
5
  SHA512:
6
- metadata.gz: 1904b47e5b0daea447eac9c638e2ea0b781758ed32e8f8e30f07e361bfa1e8bfbdce55d100f2678043d6bbe80a2ef3a130628d5b619790d615d6cd1830108392
7
- data.tar.gz: bcad22a5914ca2dfc426588ec7ccaaefe6169801d4f8b3e0366e3f71b517e1042e84a60d819bd0eed13d39b76ca435c93359fc1dafa854c05f9303e0832ed227
6
+ metadata.gz: a20e56fe585721fd0daea6ae733b0cadcd53273e9f44aaf0e783e62b11bf1bf8d2dc1c00e06e5cc6d2de55099e54b1ed62f6162e402039946f00c547a75e8334
7
+ data.tar.gz: 0547cb6578f56c46bbbe61fdb6a920e74cca7e79b5fbcca9d8dfab376b5ae97a827571a3ba9a4737ac99dd6765797f69f4538604af0c9009b33493a7a371e7ce
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007-2014, Spree Commerce, Inc. and other contributors
1
+ Copyright (c) 2007-2015, Spree Commerce, Inc. and other contributors
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
@@ -4,7 +4,6 @@ require_dependency 'spree/core/controller_helpers/strong_parameters'
4
4
  class Spree::BaseController < ApplicationController
5
5
  include Spree::Core::ControllerHelpers::Auth
6
6
  include Spree::Core::ControllerHelpers::RespondWith
7
- include Spree::Core::ControllerHelpers::SSL
8
7
  include Spree::Core::ControllerHelpers::Common
9
8
  include Spree::Core::ControllerHelpers::Search
10
9
  include Spree::Core::ControllerHelpers::Store
@@ -13,4 +12,4 @@ class Spree::BaseController < ApplicationController
13
12
  respond_to :html
14
13
  end
15
14
 
16
- require 'spree/i18n/initializer'
15
+ require 'spree/i18n/initializer'
@@ -1,35 +1,37 @@
1
1
  module Spree
2
2
  module BaseHelper
3
3
 
4
- # Defined because Rails' current_page? helper is not working when Spree is mounted at root.
5
- def current_spree_page?(url)
6
- path = request.fullpath.gsub(/^\/\//, '/')
7
- if url.is_a?(String)
8
- return path == url
9
- elsif url.is_a?(Hash)
10
- return path == spree.url_for(url)
4
+ def available_countries
5
+ checkout_zone = Zone.find_by(name: Spree::Config[:checkout_zone])
6
+
7
+ if checkout_zone && checkout_zone.kind == 'country'
8
+ countries = checkout_zone.country_list
9
+ else
10
+ countries = Country.all
11
11
  end
12
- return false
12
+
13
+ countries.collect do |country|
14
+ country.name = Spree.t(country.iso, scope: 'country_names', default: country.name)
15
+ country
16
+ end.sort_by { |c| c.name.parameterize }
13
17
  end
14
18
 
15
- def link_to_cart(text = nil)
16
- text = text ? h(text) : Spree.t('cart')
17
- css_class = nil
19
+ def display_price(product_or_variant)
20
+ product_or_variant.price_in(current_currency).display_price.to_html
21
+ end
18
22
 
19
- if simple_current_order.nil? or simple_current_order.item_count.zero?
20
- text = "#{text}: (#{Spree.t('empty')})"
21
- css_class = 'empty'
23
+ def link_to_tracking(shipment, options = {})
24
+ return unless shipment.tracking && shipment.shipping_method
25
+
26
+ if shipment.tracking_url
27
+ link_to(shipment.tracking, shipment.tracking_url, options)
22
28
  else
23
- text = "#{text}: (#{simple_current_order.item_count}) <span class='amount'>#{simple_current_order.display_total.to_html}</span>"
24
- css_class = 'full'
29
+ content_tag(:span, shipment.tracking)
25
30
  end
26
-
27
- link_to text.html_safe, spree.cart_path, :class => "cart-info #{css_class}"
28
31
  end
29
32
 
30
- # human readable list of variant options
31
- def variant_options(v, options={})
32
- v.options_text
33
+ def logo(image_path=Spree::Config[:logo])
34
+ link_to image_tag(image_path), spree.root_path
33
35
  end
34
36
 
35
37
  def meta_data
@@ -58,101 +60,6 @@ module Spree
58
60
  end.join("\n")
59
61
  end
60
62
 
61
- def body_class
62
- @body_class ||= content_for?(:sidebar) ? 'two-col' : 'one-col'
63
- @body_class
64
- end
65
-
66
- def logo(image_path=Spree::Config[:logo])
67
- link_to image_tag(image_path), spree.root_path
68
- end
69
-
70
- def flash_messages(opts = {})
71
- ignore_types = ["order_completed"].concat(Array(opts[:ignore_types]).map(&:to_s) || [])
72
-
73
- flash.each do |msg_type, text|
74
- unless ignore_types.include?(msg_type)
75
- concat(content_tag :div, text, class: "flash #{msg_type}")
76
- end
77
- end
78
- nil
79
- end
80
-
81
- def breadcrumbs(taxon, separator="&nbsp;&raquo;&nbsp;", breadcrumb_class="inline")
82
- return "" if current_page?("/") || taxon.nil?
83
-
84
- crumbs = [[Spree.t(:home), spree.root_path]]
85
-
86
- if taxon
87
- crumbs << [Spree.t(:products), products_path]
88
- crumbs += taxon.ancestors.collect { |a| [a.name, spree.nested_taxons_path(a.permalink)] } unless taxon.ancestors.empty?
89
- crumbs << [taxon.name, spree.nested_taxons_path(taxon.permalink)]
90
- else
91
- crumbs << [Spree.t(:products), products_path]
92
- end
93
-
94
- separator = raw(separator)
95
-
96
- crumbs.map! do |crumb|
97
- content_tag(:li, itemscope:"itemscope", itemtype:"http://data-vocabulary.org/Breadcrumb") do
98
- link_to(crumb.last, itemprop: "url") do
99
- content_tag(:span, crumb.first, itemprop: "title")
100
- end + (crumb == crumbs.last ? '' : separator)
101
- end
102
- end
103
-
104
- content_tag(:nav, content_tag(:ul, raw(crumbs.map(&:mb_chars).join), class: breadcrumb_class), id: 'breadcrumbs', class: 'sixteen columns')
105
- end
106
-
107
- def taxons_tree(root_taxon, current_taxon, max_level = 1)
108
- return '' if max_level < 1 || root_taxon.leaf?
109
- content_tag :ul, class: 'taxons-list' do
110
- root_taxon.children.map do |taxon|
111
- css_class = (current_taxon && current_taxon.self_and_ancestors.include?(taxon)) ? 'current' : nil
112
- content_tag :li, class: css_class do
113
- link_to(taxon.name, seo_url(taxon)) +
114
- taxons_tree(taxon, current_taxon, max_level - 1)
115
- end
116
- end.join("\n").html_safe
117
- end
118
- end
119
-
120
- def available_countries
121
- checkout_zone = Zone.find_by(name: Spree::Config[:checkout_zone])
122
-
123
- if checkout_zone && checkout_zone.kind == 'country'
124
- countries = checkout_zone.country_list
125
- else
126
- countries = Country.all
127
- end
128
-
129
- countries.collect do |country|
130
- country.name = Spree.t(country.iso, scope: 'country_names', default: country.name)
131
- country
132
- end.sort_by { |c| c.name.parameterize }
133
- end
134
-
135
- def seo_url(taxon)
136
- return spree.nested_taxons_path(taxon.permalink)
137
- end
138
-
139
- def gem_available?(name)
140
- Gem::Specification.find_by_name(name)
141
- rescue Gem::LoadError
142
- false
143
- rescue
144
- Gem.available?(name)
145
- end
146
-
147
- def display_price(product_or_variant)
148
- product_or_variant.price_in(current_currency).display_price.to_html
149
- end
150
-
151
- def pretty_time(time)
152
- [I18n.l(time.to_date, format: :long),
153
- time.strftime("%l:%M %p")].join(" ")
154
- end
155
-
156
63
  def method_missing(method_name, *args, &block)
157
64
  if image_style = image_style_from_method_name(method_name)
158
65
  define_image_method(image_style)
@@ -162,26 +69,21 @@ module Spree
162
69
  end
163
70
  end
164
71
 
165
- def link_to_tracking(shipment, options = {})
166
- return unless shipment.tracking && shipment.shipping_method
167
-
168
- if shipment.tracking_url
169
- link_to(shipment.tracking, shipment.tracking_url, options)
170
- else
171
- content_tag(:span, shipment.tracking)
172
- end
72
+ def pretty_time(time)
73
+ [I18n.l(time.to_date, format: :long), time.strftime("%l:%M %p")].join(" ")
173
74
  end
174
75
 
175
- private
76
+ def seo_url(taxon)
77
+ return spree.nested_taxons_path(taxon.permalink)
78
+ end
176
79
 
177
- # Returns style of image or nil
178
- def image_style_from_method_name(method_name)
179
- if method_name.to_s.match(/_image$/) && style = method_name.to_s.sub(/_image$/, '')
180
- possible_styles = Spree::Image.attachment_definitions[:attachment][:styles]
181
- style if style.in? possible_styles.with_indifferent_access
182
- end
80
+ # human readable list of variant options
81
+ def variant_options(v, options={})
82
+ v.options_text
183
83
  end
184
84
 
85
+ private
86
+
185
87
  def create_product_image_tag(image, product, options, style)
186
88
  options.reverse_merge! alt: image.alt.blank? ? product.name : image.alt
187
89
  image_tag image.attachment.url(style), options
@@ -205,5 +107,13 @@ module Spree
205
107
  end
206
108
  end
207
109
  end
110
+
111
+ # Returns style of image or nil
112
+ def image_style_from_method_name(method_name)
113
+ if method_name.to_s.match(/_image$/) && style = method_name.to_s.sub(/_image$/, '')
114
+ possible_styles = Spree::Image.attachment_definitions[:attachment][:styles]
115
+ style if style.in? possible_styles.with_indifferent_access
116
+ end
117
+ end
208
118
  end
209
119
  end
@@ -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;', ' ').squish), length: 100)
48
+ truncate(strip_tags(description_text.gsub('&nbsp;', ' ')), length: 100)
49
49
  else
50
50
  Spree.t(:product_has_no_description)
51
51
  end
@@ -3,21 +3,57 @@ module Spree
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- def deals_with_adjustments_for_deleted_source
7
- adjustment_scope = self.adjustments.includes(:order).references(:spree_orders)
8
-
9
- # For incomplete orders, remove the adjustment completely.
10
- adjustment_scope.where("spree_orders.completed_at IS NULL").destroy_all
11
-
12
- # For complete orders, the source will be invalid.
13
- # Therefore we nullify the source_id, leaving the adjustment in place.
14
- # This would mean that the order's total is not altered at all.
15
- adjustment_scope.where("spree_orders.completed_at IS NOT NULL").each do |adjustment|
16
- adjustment.update_columns(
17
- source_id: nil,
18
- updated_at: Time.now,
19
- )
20
- end
6
+ has_many :adjustments, as: :source
7
+ before_destroy :deals_with_adjustments_for_deleted_source
8
+ end
9
+
10
+ protected
11
+
12
+ def create_adjustment(order, adjustable, included = nil)
13
+ amount = compute_amount(adjustable)
14
+ return if amount == 0
15
+ adjustments.new(order: order,
16
+ adjustable: adjustable,
17
+ label: label(amount),
18
+ amount: amount,
19
+ included: included).save
20
+ end
21
+
22
+ def create_unique_adjustment(order, adjustable)
23
+ return if already_adjusted?(adjustable)
24
+ create_adjustment(order, adjustable)
25
+ end
26
+
27
+ def create_unique_adjustments(order, adjustables)
28
+ adjustables.where.not(id: already_adjusted_ids(order)).map do |adjustable|
29
+ create_adjustment(order, adjustable) if !block_given? || yield(adjustable)
30
+ end.any?
31
+ end
32
+
33
+ private
34
+
35
+ def already_adjusted_ids(order)
36
+ adjustments.where(order: order).pluck(:adjustable_id)
37
+ end
38
+
39
+ def already_adjusted?(adjustable)
40
+ adjustments.where(adjustable: adjustable).exists?
41
+ end
42
+
43
+ def deals_with_adjustments_for_deleted_source
44
+ adjustment_scope = adjustments.includes(:order).references(:spree_orders)
45
+
46
+ # For incomplete orders, remove the adjustment completely.
47
+ adjustment_scope.where("spree_orders.completed_at IS NULL").destroy_all
48
+
49
+ # For complete orders, the source will be invalid.
50
+ # Therefore we nullify the source_id, leaving the adjustment in place.
51
+ # This would mean that the order's total is not altered at all.
52
+ adjustment_scope.where("spree_orders.completed_at IS NOT NULL").each do |adjustment|
53
+ adjustment.update_columns(
54
+ source_id: nil,
55
+ updated_at: Time.now,
56
+ )
21
57
  end
22
58
  end
23
59
  end
@@ -6,6 +6,7 @@ module Spree
6
6
  has_one :calculator, class_name: "Spree::Calculator", as: :calculable, inverse_of: :calculable, dependent: :destroy, autosave: true
7
7
  accepts_nested_attributes_for :calculator
8
8
  validates :calculator, presence: true
9
+ delegate :compute, to: :calculator
9
10
 
10
11
  def self.calculators
11
12
  spree_calculators.send model_name_without_spree_namespace
@@ -0,0 +1,32 @@
1
+ module Spree
2
+ module DisplayMoney
3
+ ##
4
+ # Takes a list of methods that the base object wants to be able to use
5
+ # to display with Spree::Money, and turns them into display_* methods.
6
+ # Intended to help clean up some of the presentational logic that exists
7
+ # at the model layer.
8
+ #
9
+ #
10
+ # ==== Examples
11
+ # Decorate a method, with the default option of using the base object's
12
+ # currency
13
+ #
14
+ # extend Spree::DisplayMoney
15
+ # money_methods :tax_amount, :price
16
+ #
17
+ # Decorate a method, but with some additional options
18
+ # extend Spree::DisplayMoney
19
+ # money_methods tax_amount: { currency: "CAD", no_cents: true }, :price
20
+ def money_methods(*args)
21
+ args.each do |money_method|
22
+ money_method = { money_method => {} } unless money_method.is_a? Hash
23
+ money_method.each do |method_name, opts|
24
+ define_method("display_#{method_name}") do
25
+ default_opts = respond_to?(:currency) ? { currency: currency } : {}
26
+ Spree::Money.new(send(method_name), default_opts.merge(opts))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -4,7 +4,7 @@ module Spree
4
4
 
5
5
  included do
6
6
  scope :active, -> { where(active: true) }
7
- default_scope -> { order("LOWER(#{self.table_name}.name)") }
7
+ default_scope { order("LOWER(#{self.table_name}.name)") }
8
8
 
9
9
  validates :name, presence: true, uniqueness: { case_sensitive: false }
10
10
  end
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ module NumberGenerator
3
+ extend ActiveSupport::Concern
4
+
5
+ NUMBER_LENGTH = 9
6
+ NUMBER_LETTERS = false
7
+ NUMBER_PREFIX = 'N'
8
+
9
+ included do
10
+ before_validation :generate_number, on: :create # generate number before make_permalink
11
+ validates :number, uniqueness: true
12
+ end
13
+
14
+ def self.by_number(number)
15
+ where(number: number)
16
+ end
17
+
18
+ def generate_number(options = {})
19
+ options[:length] ||= NUMBER_LENGTH
20
+ options[:letters] ||= NUMBER_LETTERS
21
+ options[:prefix] ||= NUMBER_PREFIX
22
+
23
+ possible = (0..9).to_a
24
+ possible += ('A'..'Z').to_a if options[:letters]
25
+
26
+ self.number ||= loop do
27
+ # Make a random number.
28
+ random = "#{options[:prefix]}#{(0...options[:length]).map { possible.shuffle.first }.join}"
29
+ # Use the random number if no other order exists with it.
30
+ if self.class.exists?(number: random)
31
+ # If over half of all possible options are taken add another digit.
32
+ options[:length] += 1 if self.class.count > (10 ** options[:length] / 2)
33
+ else
34
+ break random
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,13 +1,12 @@
1
1
  module Spree
2
2
  module UserReporting
3
+ extend DisplayMoney
4
+ money_methods :lifetime_value, :average_order_value
5
+
3
6
  def lifetime_value
4
7
  spree_orders.complete.pluck(:total).sum
5
8
  end
6
9
 
7
- def display_lifetime_value
8
- Spree::Money.new(lifetime_value)
9
- end
10
-
11
10
  def order_count
12
11
  BigDecimal(spree_orders.complete.count)
13
12
  end
@@ -19,9 +18,5 @@ module Spree
19
18
  BigDecimal("0.00")
20
19
  end
21
20
  end
22
-
23
- def display_average_order_value
24
- Spree::Money.new(average_order_value)
25
- end
26
21
  end
27
22
  end