solidus_core 2.9.0 → 2.10.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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +4 -4
  3. data/app/helpers/spree/products_helper.rb +2 -1
  4. data/app/jobs/spree/promotion_code_batch_job.rb +2 -2
  5. data/app/models/concerns/spree/user_address_book.rb +2 -2
  6. data/app/models/concerns/spree/user_methods.rb +2 -2
  7. data/app/models/spree/address.rb +13 -17
  8. data/app/models/spree/adjustment.rb +20 -9
  9. data/app/models/spree/asset.rb +1 -1
  10. data/app/models/spree/base.rb +0 -2
  11. data/app/models/spree/calculator/price_sack.rb +1 -1
  12. data/app/models/spree/calculator/shipping/flexi_rate.rb +2 -2
  13. data/app/models/spree/calculator/tiered_flat_rate.rb +5 -5
  14. data/app/models/spree/calculator/tiered_percent.rb +6 -6
  15. data/app/models/spree/calculator.rb +1 -1
  16. data/app/models/spree/carton.rb +3 -3
  17. data/app/models/spree/classification.rb +2 -2
  18. data/app/models/spree/credit_card.rb +4 -4
  19. data/app/models/spree/customer_return.rb +1 -1
  20. data/app/models/spree/image/paperclip_attachment.rb +1 -1
  21. data/app/models/spree/inventory_unit.rb +5 -23
  22. data/app/models/spree/line_item.rb +4 -4
  23. data/app/models/spree/line_item_action.rb +2 -2
  24. data/app/models/spree/log_entry.rb +1 -1
  25. data/app/models/spree/option_value.rb +1 -1
  26. data/app/models/spree/option_values_variant.rb +2 -2
  27. data/app/models/spree/order/checkout.rb +1 -1
  28. data/app/models/spree/order/payments.rb +2 -2
  29. data/app/models/spree/order.rb +11 -10
  30. data/app/models/spree/order_cancellations.rb +1 -1
  31. data/app/models/spree/order_capturing.rb +2 -2
  32. data/app/models/spree/order_contents.rb +2 -2
  33. data/app/models/spree/order_mutex.rb +1 -1
  34. data/app/models/spree/order_promotion.rb +3 -3
  35. data/app/models/spree/order_shipping.rb +1 -1
  36. data/app/models/spree/order_taxation.rb +3 -3
  37. data/app/models/spree/payment/processing.rb +3 -3
  38. data/app/models/spree/payment.rb +8 -45
  39. data/app/models/spree/payment_capture_event.rb +1 -1
  40. data/app/models/spree/payment_method/bogus_credit_card.rb +1 -1
  41. data/app/models/spree/payment_method.rb +5 -2
  42. data/app/models/spree/payment_source.rb +1 -1
  43. data/app/models/spree/price.rb +2 -2
  44. data/app/models/spree/product/scopes.rb +218 -210
  45. data/app/models/spree/product.rb +5 -5
  46. data/app/models/spree/product_option_type.rb +2 -2
  47. data/app/models/spree/product_promotion_rule.rb +2 -2
  48. data/app/models/spree/product_property.rb +2 -2
  49. data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +1 -1
  50. data/app/models/spree/promotion/actions/free_shipping.rb +1 -1
  51. data/app/models/spree/promotion/rules/option_value.rb +2 -2
  52. data/app/models/spree/promotion/rules/product.rb +3 -3
  53. data/app/models/spree/promotion.rb +28 -13
  54. data/app/models/spree/promotion_action.rb +2 -2
  55. data/app/models/spree/promotion_chooser.rb +2 -2
  56. data/app/models/spree/promotion_code/batch_builder.rb +3 -3
  57. data/app/models/spree/promotion_code.rb +11 -10
  58. data/app/models/spree/promotion_code_batch.rb +1 -1
  59. data/app/models/spree/promotion_rule.rb +2 -2
  60. data/app/models/spree/promotion_rule_role.rb +2 -2
  61. data/app/models/spree/promotion_rule_store.rb +2 -2
  62. data/app/models/spree/promotion_rule_taxon.rb +2 -2
  63. data/app/models/spree/promotion_rule_user.rb +2 -2
  64. data/app/models/spree/refund.rb +5 -5
  65. data/app/models/spree/reimbursement/credit.rb +2 -2
  66. data/app/models/spree/reimbursement/reimbursement_type_engine.rb +1 -1
  67. data/app/models/spree/reimbursement.rb +5 -13
  68. data/app/models/spree/reimbursement_tax_calculator.rb +1 -1
  69. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +2 -2
  70. data/app/models/spree/return_authorization.rb +4 -10
  71. data/app/models/spree/return_item/eligibility_validator/default.rb +1 -1
  72. data/app/models/spree/return_item.rb +13 -52
  73. data/app/models/spree/role_user.rb +2 -2
  74. data/app/models/spree/shipment.rb +7 -41
  75. data/app/models/spree/shipping_calculator.rb +0 -4
  76. data/app/models/spree/shipping_manifest.rb +3 -3
  77. data/app/models/spree/shipping_method.rb +2 -2
  78. data/app/models/spree/shipping_method_category.rb +2 -2
  79. data/app/models/spree/shipping_method_stock_location.rb +2 -2
  80. data/app/models/spree/shipping_method_zone.rb +2 -2
  81. data/app/models/spree/shipping_rate.rb +2 -2
  82. data/app/models/spree/shipping_rate_tax.rb +2 -2
  83. data/app/models/spree/state.rb +2 -2
  84. data/app/models/spree/state_change.rb +2 -2
  85. data/app/models/spree/stock/differentiator.rb +1 -1
  86. data/app/models/spree/stock/package.rb +1 -1
  87. data/app/models/spree/stock_item.rb +3 -3
  88. data/app/models/spree/stock_location.rb +2 -2
  89. data/app/models/spree/stock_movement.rb +2 -2
  90. data/app/models/spree/stock_quantities.rb +13 -12
  91. data/app/models/spree/store_credit.rb +8 -8
  92. data/app/models/spree/store_credit_event.rb +3 -3
  93. data/app/models/spree/store_payment_method.rb +2 -2
  94. data/app/models/spree/store_shipping_method.rb +2 -2
  95. data/app/models/spree/tax_calculator/default.rb +0 -4
  96. data/app/models/spree/tax_calculator/shipping_rate.rb +0 -3
  97. data/app/models/spree/tax_rate.rb +5 -1
  98. data/app/models/spree/tax_rate_tax_category.rb +2 -2
  99. data/app/models/spree/taxon/paperclip_attachment.rb +13 -0
  100. data/app/models/spree/unit_cancel.rb +5 -2
  101. data/app/models/spree/user_address.rb +2 -2
  102. data/app/models/spree/user_last_url_storer/rules/authentication_rule.rb +36 -0
  103. data/app/models/spree/user_last_url_storer.rb +46 -0
  104. data/app/models/spree/user_stock_location.rb +2 -2
  105. data/app/models/spree/variant/scopes.rb +37 -29
  106. data/app/models/spree/variant.rb +10 -10
  107. data/app/models/spree/variant_property_rule.rb +1 -1
  108. data/app/models/spree/variant_property_rule_condition.rb +2 -2
  109. data/app/models/spree/variant_property_rule_value.rb +2 -2
  110. data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
  111. data/app/models/spree/wallet_payment_source.rb +2 -2
  112. data/app/models/spree/zone.rb +1 -1
  113. data/app/models/spree/zone_member.rb +2 -2
  114. data/config/initializers/inflections.rb +5 -0
  115. data/config/initializers/money.rb +2 -0
  116. data/config/locales/en.yml +34 -3
  117. data/lib/generators/spree/dummy/dummy_generator.rb +2 -0
  118. data/lib/generators/spree/install/install_generator.rb +3 -0
  119. data/lib/generators/spree/install/templates/config/initializers/spree.rb.tt +8 -0
  120. data/lib/spree/app_configuration.rb +18 -3
  121. data/lib/spree/core/controller_helpers/auth.rb +1 -13
  122. data/lib/spree/core/engine.rb +2 -2
  123. data/lib/spree/core/environment_extension.rb +9 -0
  124. data/lib/spree/core/importer/order.rb +28 -28
  125. data/lib/spree/core/importer/product.rb +2 -2
  126. data/lib/spree/core/product_filters.rb +15 -15
  127. data/lib/spree/core/role_configuration.rb +2 -2
  128. data/lib/spree/core/search/variant.rb +1 -1
  129. data/lib/spree/core/state_machines/inventory_unit.rb +42 -0
  130. data/lib/spree/core/state_machines/payment.rb +61 -0
  131. data/lib/spree/core/state_machines/reimbursement.rb +33 -0
  132. data/lib/spree/core/state_machines/return_authorization.rb +32 -0
  133. data/lib/spree/core/state_machines/return_item/acceptance_status.rb +51 -0
  134. data/lib/spree/core/state_machines/return_item/reception_status.rb +42 -0
  135. data/lib/spree/core/state_machines/shipment.rb +58 -0
  136. data/lib/spree/core/state_machines.rb +78 -0
  137. data/lib/spree/core/stock_configuration.rb +1 -0
  138. data/lib/spree/core/validators/email.rb +1 -8
  139. data/lib/spree/core/version.rb +1 -1
  140. data/lib/spree/core.rb +12 -0
  141. data/lib/spree/money.rb +2 -2
  142. data/lib/spree/permission_sets/default_customer.rb +1 -1
  143. data/lib/spree/permission_sets/user_management.rb +3 -0
  144. data/lib/spree/permitted_attributes.rb +3 -3
  145. data/lib/spree/preferences/static_model_preferences.rb +2 -2
  146. data/lib/spree/testing_support/dummy_app/rake_tasks.rb +6 -2
  147. data/lib/spree/testing_support/dummy_app.rb +4 -1
  148. data/lib/spree/testing_support/factories/inventory_unit_factory.rb +8 -1
  149. data/lib/spree/testing_support/factories/promotion_factory.rb +7 -0
  150. data/lib/spree/testing_support/factories/stock_package_factory.rb +1 -1
  151. data/lib/spree/testing_support/preferences.rb +54 -15
  152. data/solidus_core.gemspec +6 -6
  153. data/spec/lib/search/base_spec.rb +5 -1
  154. data/spec/lib/search/variant_spec.rb +1 -1
  155. data/spec/lib/spree/core/environment_extension_spec.rb +12 -1
  156. data/spec/lib/spree/core/stock_configuration_spec.rb +36 -0
  157. data/spec/lib/spree/core/validators/email_spec.rb +18 -18
  158. data/spec/lib/spree/event_spec.rb +15 -3
  159. data/spec/models/spree/address_spec.rb +23 -0
  160. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +1 -1
  161. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +1 -1
  162. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +1 -1
  163. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +2 -2
  164. data/spec/models/spree/calculator/shipping/per_item_spec.rb +1 -1
  165. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +24 -15
  166. data/spec/models/spree/carton_spec.rb +10 -2
  167. data/spec/models/spree/classification_spec.rb +21 -9
  168. data/spec/models/spree/concerns/user_address_book_spec.rb +4 -4
  169. data/spec/models/spree/concerns/user_methods_spec.rb +5 -4
  170. data/spec/models/spree/credit_card_spec.rb +2 -2
  171. data/spec/models/spree/customer_return_spec.rb +1 -1
  172. data/spec/models/spree/order/checkout_spec.rb +1 -1
  173. data/spec/models/spree/order/outstanding_balance_integration_spec.rb +5 -5
  174. data/spec/models/spree/order/payment_spec.rb +1 -1
  175. data/spec/models/spree/order_contents_spec.rb +1 -1
  176. data/spec/models/spree/order_inventory_spec.rb +3 -3
  177. data/spec/models/spree/order_merger_spec.rb +3 -3
  178. data/spec/models/spree/order_shipping_spec.rb +1 -1
  179. data/spec/models/spree/order_spec.rb +14 -21
  180. data/spec/models/spree/order_updater_spec.rb +4 -3
  181. data/spec/models/spree/payment_create_spec.rb +6 -16
  182. data/spec/models/spree/payment_spec.rb +12 -12
  183. data/spec/models/spree/permission_sets/user_management_spec.rb +2 -0
  184. data/spec/models/spree/preference_spec.rb +4 -4
  185. data/spec/models/spree/preferences/preferable_spec.rb +3 -3
  186. data/spec/models/spree/preferences/statically_configurable_spec.rb +2 -2
  187. data/spec/models/spree/promotion/rules/first_repeat_purchase_since_spec.rb +2 -2
  188. data/spec/models/spree/promotion/rules/nth_order_spec.rb +2 -2
  189. data/spec/models/spree/promotion_rule_spec.rb +6 -6
  190. data/spec/models/spree/promotion_spec.rb +71 -54
  191. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +3 -3
  192. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +1 -1
  193. data/spec/models/spree/return_item_spec.rb +11 -11
  194. data/spec/models/spree/returns_calculator_spec.rb +2 -2
  195. data/spec/models/spree/shipment_spec.rb +6 -6
  196. data/spec/models/spree/shipping_calculator_spec.rb +1 -13
  197. data/spec/models/spree/shipping_method_spec.rb +32 -0
  198. data/spec/models/spree/stock/availability_validator_spec.rb +2 -2
  199. data/spec/models/spree/stock/differentiator_spec.rb +2 -2
  200. data/spec/models/spree/stock/estimator_spec.rb +3 -3
  201. data/spec/models/spree/stock/inventory_units_finalizer_spec.rb +4 -4
  202. data/spec/models/spree/stock/package_spec.rb +28 -28
  203. data/spec/models/spree/stock/quantifier_spec.rb +3 -3
  204. data/spec/models/spree/stock/simple_coordinator_spec.rb +11 -11
  205. data/spec/models/spree/stock/splitter/base_spec.rb +4 -4
  206. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +7 -7
  207. data/spec/models/spree/stock_quantities_spec.rb +1 -1
  208. data/spec/models/spree/store_credit_spec.rb +8 -8
  209. data/spec/models/spree/tax_category_spec.rb +1 -1
  210. data/spec/models/spree/tax_rate_spec.rb +1 -0
  211. data/spec/models/spree/taxon_spec.rb +2 -2
  212. data/spec/models/spree/taxons/paperclip_attachment_spec.rb +29 -0
  213. data/spec/models/spree/unit_cancel_spec.rb +5 -0
  214. data/spec/models/spree/user_last_url_storer/rules/authentication_rule_spec.rb +31 -0
  215. data/spec/models/spree/user_last_url_storer_spec.rb +60 -0
  216. data/spec/models/spree/user_spec.rb +3 -3
  217. metadata +46 -41
  218. data/spec/migrate/20190106184413_remove_code_from_spree_promotions_spec.rb +0 -148
  219. data/spec/models/spree/order/updating_spec.rb +0 -18
@@ -7,7 +7,7 @@ module Spree
7
7
 
8
8
  attr_reader :eligibility_errors
9
9
 
10
- belongs_to :promotion_category
10
+ belongs_to :promotion_category, optional: true
11
11
 
12
12
  has_many :promotion_rules, autosave: true, dependent: :destroy, inverse_of: :promotion
13
13
  alias_method :rules, :promotion_rules
@@ -126,9 +126,12 @@ module Spree
126
126
  # called anytime order.recalculate happens
127
127
  def eligible?(promotable, promotion_code: nil)
128
128
  return false if inactive?
129
- return false if usage_limit_exceeded?
130
- return false if promotion_code && promotion_code.usage_limit_exceeded?
131
129
  return false if blacklisted?(promotable)
130
+
131
+ excluded_orders = eligibility_excluded_orders(promotable)
132
+ return false if usage_limit_exceeded?(excluded_orders: excluded_orders)
133
+ return false if promotion_code&.usage_limit_exceeded?(excluded_orders: excluded_orders)
134
+
132
135
  !!eligible_rules(promotable, {})
133
136
  end
134
137
 
@@ -138,7 +141,8 @@ module Spree
138
141
  def eligible_rules(promotable, options = {})
139
142
  # Promotions without rules are eligible by default.
140
143
  return [] if rules.none?
141
- eligible = lambda { |r| r.eligible?(promotable, options) }
144
+
145
+ eligible = lambda { |rule| rule.eligible?(promotable, options) }
142
146
  specific_rules = rules.for(promotable)
143
147
  return [] if specific_rules.none?
144
148
 
@@ -165,23 +169,23 @@ module Spree
165
169
 
166
170
  # Whether the promotion has exceeded it's usage restrictions.
167
171
  #
172
+ # @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage limit
168
173
  # @return true or false
169
- def usage_limit_exceeded?
174
+ def usage_limit_exceeded?(excluded_orders: [])
170
175
  if usage_limit
171
- usage_count >= usage_limit
176
+ usage_count(excluded_orders: excluded_orders) >= usage_limit
172
177
  end
173
178
  end
174
179
 
175
180
  # Number of times the code has been used overall
176
181
  #
182
+ # @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage count
177
183
  # @return [Integer] usage count
178
- def usage_count
179
- Spree::Adjustment.eligible.
180
- promotion.
181
- where(source_id: actions.map(&:id)).
182
- joins(:order).
183
- merge(Spree::Order.complete).
184
- distinct.
184
+ def usage_count(excluded_orders: [])
185
+ Spree::Adjustment.promotion.
186
+ eligible.
187
+ in_completed_orders(excluded_orders: excluded_orders).
188
+ where(source_id: actions).
185
189
  count(:order_id)
186
190
  end
187
191
 
@@ -255,8 +259,19 @@ module Spree
255
259
 
256
260
  def apply_automatically_disallowed_with_codes_or_paths
257
261
  return unless apply_automatically
262
+
258
263
  errors.add(:apply_automatically, :disallowed_with_code) if codes.any?
259
264
  errors.add(:apply_automatically, :disallowed_with_path) if path.present?
260
265
  end
266
+
267
+ def eligibility_excluded_orders(promotable)
268
+ if promotable.is_a?(Spree::Order)
269
+ [promotable]
270
+ elsif promotable.respond_to?(:order)
271
+ [promotable.order]
272
+ else
273
+ []
274
+ end
275
+ end
261
276
  end
262
277
  end
@@ -14,9 +14,9 @@ module Spree
14
14
  include Discard::Model
15
15
  self.discard_column = :deleted_at
16
16
 
17
- belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_actions
17
+ belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_actions, optional: true
18
18
 
19
- scope :of_type, ->(t) { where(type: Array.wrap(t).map(&:to_s)) }
19
+ scope :of_type, ->(type) { where(type: Array.wrap(type).map(&:to_s)) }
20
20
  scope :shipping, -> { of_type(Spree::Config.environment.promotions.shipping_actions.to_a) }
21
21
 
22
22
  # Updates the state of the order or performs some other action depending on
@@ -26,8 +26,8 @@ module Spree
26
26
 
27
27
  # @return The best promotion from this set of adjustments.
28
28
  def best_promotion_adjustment
29
- @best_promotion_adjustment ||= @adjustments.select(&:eligible?).min_by do |a|
30
- [a.amount, -a.id]
29
+ @best_promotion_adjustment ||= @adjustments.select(&:eligible?).min_by do |adjustment|
30
+ [adjustment.amount, -adjustment.id]
31
31
  end
32
32
  end
33
33
  end
@@ -33,12 +33,12 @@ class ::Spree::PromotionCode::BatchBuilder
33
33
  def build_promotion_codes
34
34
  generate_random_codes
35
35
  promotion_code_batch.update!(state: "completed")
36
- rescue StandardError => e
36
+ rescue StandardError => error
37
37
  promotion_code_batch.update!(
38
- error: e.inspect,
38
+ error: error.inspect,
39
39
  state: "failed"
40
40
  )
41
- raise e
41
+ raise error
42
42
  end
43
43
 
44
44
  private
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Spree::PromotionCode < Spree::Base
4
- belongs_to :promotion, inverse_of: :codes
5
- belongs_to :promotion_code_batch, class_name: "Spree::PromotionCodeBatch"
4
+ belongs_to :promotion, inverse_of: :codes, optional: true
5
+ belongs_to :promotion_code_batch, class_name: "Spree::PromotionCodeBatch", optional: true
6
6
  has_many :adjustments
7
7
 
8
8
  validates :value, presence: true, uniqueness: { allow_blank: true }
@@ -14,22 +14,23 @@ class Spree::PromotionCode < Spree::Base
14
14
 
15
15
  # Whether the promotion code has exceeded its usage restrictions
16
16
  #
17
+ # @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage limit
17
18
  # @return true or false
18
- def usage_limit_exceeded?
19
+ def usage_limit_exceeded?(excluded_orders: [])
19
20
  if usage_limit
20
- usage_count >= usage_limit
21
+ usage_count(excluded_orders: excluded_orders) >= usage_limit
21
22
  end
22
23
  end
23
24
 
24
25
  # Number of times the code has been used overall
25
26
  #
27
+ # @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage count
26
28
  # @return [Integer] usage count
27
- def usage_count
28
- adjustments.eligible.
29
- joins(:order).
30
- merge(Spree::Order.complete).
31
- distinct.
32
- count(:order_id)
29
+ def usage_count(excluded_orders: [])
30
+ adjustments.
31
+ eligible.
32
+ in_completed_orders(excluded_orders: excluded_orders).
33
+ count(:order_id)
33
34
  end
34
35
 
35
36
  def usage_limit
@@ -5,7 +5,7 @@ module Spree
5
5
  class CantProcessStartedBatch < StandardError
6
6
  end
7
7
 
8
- belongs_to :promotion, class_name: "Spree::Promotion"
8
+ belongs_to :promotion, class_name: "Spree::Promotion", optional: true
9
9
  has_many :promotion_codes, class_name: "Spree::PromotionCode", dependent: :destroy
10
10
 
11
11
  validates :number_of_codes, numericality: { greater_than: 0 }
@@ -3,9 +3,9 @@
3
3
  module Spree
4
4
  # Base class for all promotion rules
5
5
  class PromotionRule < Spree::Base
6
- belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_rules
6
+ belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_rules, optional: true
7
7
 
8
- scope :of_type, ->(t) { where(type: t) }
8
+ scope :of_type, ->(type) { where(type: type) }
9
9
 
10
10
  validates :promotion, presence: true
11
11
  validate :unique_per_promotion, on: :create
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Spree
4
4
  class PromotionRuleRole < ActiveRecord::Base
5
- belongs_to :promotion_rule, class_name: 'Spree::PromotionRule'
6
- belongs_to :role, class_name: 'Spree::Role'
5
+ belongs_to :promotion_rule, class_name: 'Spree::PromotionRule', optional: true
6
+ belongs_to :role, class_name: 'Spree::Role', optional: true
7
7
  end
8
8
  end
@@ -4,7 +4,7 @@ module Spree
4
4
  class PromotionRuleStore < Spree::Base
5
5
  self.table_name = "spree_promotion_rules_stores"
6
6
 
7
- belongs_to :promotion_rule, class_name: "Spree::PromotionRule"
8
- belongs_to :store, class_name: "Spree::Store"
7
+ belongs_to :promotion_rule, class_name: "Spree::PromotionRule", optional: true
8
+ belongs_to :store, class_name: "Spree::Store", optional: true
9
9
  end
10
10
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Spree
4
4
  class PromotionRuleTaxon < Spree::Base
5
- belongs_to :promotion_rule
6
- belongs_to :taxon
5
+ belongs_to :promotion_rule, optional: true
6
+ belongs_to :taxon, optional: true
7
7
  end
8
8
  end
@@ -4,7 +4,7 @@ module Spree
4
4
  class PromotionRuleUser < Spree::Base
5
5
  self.table_name = 'spree_promotion_rules_users'
6
6
 
7
- belongs_to :promotion_rule, class_name: 'Spree::PromotionRule'
8
- belongs_to :user, class_name: Spree::UserClassHandle.new
7
+ belongs_to :promotion_rule, class_name: 'Spree::PromotionRule', optional: true
8
+ belongs_to :user, class_name: Spree::UserClassHandle.new, optional: true
9
9
  end
10
10
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Spree
4
4
  class Refund < Spree::Base
5
- belongs_to :payment, inverse_of: :refunds
6
- belongs_to :reason, class_name: 'Spree::RefundReason', foreign_key: :refund_reason_id
7
- belongs_to :reimbursement, inverse_of: :refunds
5
+ belongs_to :payment, inverse_of: :refunds, optional: true
6
+ belongs_to :reason, class_name: 'Spree::RefundReason', foreign_key: :refund_reason_id, optional: true
7
+ belongs_to :reimbursement, inverse_of: :refunds, optional: true
8
8
 
9
9
  has_many :log_entries, as: :source
10
10
 
@@ -68,8 +68,8 @@ module Spree
68
68
  end
69
69
 
70
70
  response
71
- rescue ActiveMerchant::ConnectionError => e
72
- logger.error(I18n.t('spree.gateway_error') + " #{e.inspect}")
71
+ rescue ActiveMerchant::ConnectionError => error
72
+ logger.error(I18n.t('spree.gateway_error') + " #{error.inspect}")
73
73
  raise Core::GatewayError.new(I18n.t('spree.unable_to_connect_to_gateway'))
74
74
  end
75
75
 
@@ -6,8 +6,8 @@ module Spree
6
6
  class_attribute :default_creditable_class
7
7
  self.default_creditable_class = Spree::StoreCredit
8
8
 
9
- belongs_to :reimbursement, inverse_of: :credits
10
- belongs_to :creditable, polymorphic: true
9
+ belongs_to :reimbursement, inverse_of: :credits, optional: true
10
+ belongs_to :creditable, polymorphic: true, optional: true
11
11
 
12
12
  validates :creditable, presence: true
13
13
 
@@ -18,7 +18,7 @@ module Spree
18
18
 
19
19
  def initialize(return_items)
20
20
  @return_items = return_items
21
- @reimbursement_type_hash = Hash.new { |h, k| h[k] = [] }
21
+ @reimbursement_type_hash = Hash.new { |hash, key| hash[key] = [] }
22
22
  end
23
23
 
24
24
  def calculate_reimbursement_types
@@ -4,8 +4,8 @@ module Spree
4
4
  class Reimbursement < Spree::Base
5
5
  class IncompleteReimbursementError < StandardError; end
6
6
 
7
- belongs_to :order, inverse_of: :reimbursements
8
- belongs_to :customer_return, inverse_of: :reimbursements, touch: true
7
+ belongs_to :order, inverse_of: :reimbursements, optional: true
8
+ belongs_to :customer_return, inverse_of: :reimbursements, touch: true, optional: true
9
9
 
10
10
  has_many :refunds, inverse_of: :reimbursement
11
11
  has_many :credits, inverse_of: :reimbursement, class_name: 'Spree::Reimbursement::Credit'
@@ -59,15 +59,7 @@ module Spree
59
59
  class_attribute :reimbursement_failure_hooks
60
60
  self.reimbursement_failure_hooks = []
61
61
 
62
- state_machine :reimbursement_status, initial: :pending do
63
- event :errored do
64
- transition to: :errored, from: [:pending, :errored]
65
- end
66
-
67
- event :reimbursed do
68
- transition to: :reimbursed, from: [:pending, :errored]
69
- end
70
- end
62
+ include ::Spree::Config.state_machines.reimbursement
71
63
 
72
64
  class << self
73
65
  def build_from_customer_return(customer_return)
@@ -112,11 +104,11 @@ module Spree
112
104
  if unpaid_amount_within_tolerance?
113
105
  reimbursed!
114
106
  Spree::Event.fire 'reimbursement_reimbursed', reimbursement: self
115
- reimbursement_success_hooks.each { |h| h.call self }
107
+ reimbursement_success_hooks.each { |hook| hook.call self }
116
108
  else
117
109
  errored!
118
110
  Spree::Event.fire 'reimbursement_errored', reimbursement: self
119
- reimbursement_failure_hooks.each { |h| h.call self }
111
+ reimbursement_failure_hooks.each { |hook| hook.call self }
120
112
  end
121
113
 
122
114
  if errored?
@@ -25,7 +25,7 @@ module Spree
25
25
  additional_tax_total = percent_of_tax * return_item.inventory_unit.additional_tax_total
26
26
  included_tax_total = percent_of_tax * return_item.inventory_unit.included_tax_total
27
27
 
28
- return_item.update_attributes!({
28
+ return_item.update!({
29
29
  additional_tax_total: additional_tax_total,
30
30
  included_tax_total: included_tax_total
31
31
  })
@@ -63,8 +63,8 @@ module Spree
63
63
 
64
64
  def sorted_eligible_refund_payments(payments)
65
65
  if eligible_refund_methods = self.eligible_refund_methods
66
- payments = payments.select { |p| eligible_refund_methods.include? p.payment_method.class }
67
- payments = payments.sort_by { |p| eligible_refund_methods.index(p.payment_method.class) }
66
+ payments = payments.select { |payment| eligible_refund_methods.include? payment.payment_method.class }
67
+ payments = payments.sort_by { |payment| eligible_refund_methods.index(payment.payment_method.class) }
68
68
  end
69
69
  payments
70
70
  end
@@ -4,14 +4,14 @@ module Spree
4
4
  # Models the return of Inventory Units to a Stock Location for an Order.
5
5
  #
6
6
  class ReturnAuthorization < Spree::Base
7
- belongs_to :order, class_name: 'Spree::Order', inverse_of: :return_authorizations
7
+ belongs_to :order, class_name: 'Spree::Order', inverse_of: :return_authorizations, optional: true
8
8
 
9
9
  has_many :return_items, inverse_of: :return_authorization, dependent: :destroy
10
10
  has_many :inventory_units, through: :return_items, dependent: :nullify
11
11
  has_many :customer_returns, through: :return_items
12
12
 
13
- belongs_to :stock_location
14
- belongs_to :reason, class_name: 'Spree::ReturnReason', foreign_key: :return_reason_id
13
+ belongs_to :stock_location, optional: true
14
+ belongs_to :reason, class_name: 'Spree::ReturnReason', foreign_key: :return_reason_id, optional: true
15
15
 
16
16
  before_create :generate_number
17
17
 
@@ -22,13 +22,7 @@ module Spree
22
22
  validate :must_have_shipped_units, on: :create
23
23
  validate :no_previously_exchanged_inventory_units, on: :create
24
24
 
25
- state_machine initial: :authorized do
26
- before_transition to: :canceled, do: :cancel_return_items
27
-
28
- event :cancel do
29
- transition to: :canceled, from: :authorized, if: lambda { |return_authorization| return_authorization.can_cancel_return_items? }
30
- end
31
- end
25
+ include ::Spree::Config.state_machines.return_authorization
32
26
 
33
27
  extend DisplayMoney
34
28
  money_methods :pre_tax_total, :amount, :total_excluding_vat
@@ -28,7 +28,7 @@ module Spree
28
28
  private
29
29
 
30
30
  def validators
31
- @validators ||= permitted_eligibility_validators.map{ |v| v.new(@return_item) }
31
+ @validators ||= permitted_eligibility_validators.map{ |validator| validator.new(@return_item) }
32
32
  end
33
33
  end
34
34
  end
@@ -29,15 +29,15 @@ module Spree
29
29
  class_attribute :refund_amount_calculator
30
30
  self.refund_amount_calculator = Calculator::Returns::DefaultRefundAmount
31
31
 
32
- belongs_to :return_authorization, inverse_of: :return_items
33
- belongs_to :inventory_unit, inverse_of: :return_items
34
- belongs_to :exchange_variant, class_name: 'Spree::Variant'
35
- belongs_to :exchange_inventory_unit, class_name: 'Spree::InventoryUnit', inverse_of: :original_return_item
36
- belongs_to :customer_return, inverse_of: :return_items
37
- belongs_to :reimbursement, inverse_of: :return_items
38
- belongs_to :preferred_reimbursement_type, class_name: 'Spree::ReimbursementType'
39
- belongs_to :override_reimbursement_type, class_name: 'Spree::ReimbursementType'
40
- belongs_to :return_reason, class_name: 'Spree::ReturnReason', foreign_key: :return_reason_id
32
+ belongs_to :return_authorization, inverse_of: :return_items, optional: true
33
+ belongs_to :inventory_unit, inverse_of: :return_items, optional: true
34
+ belongs_to :exchange_variant, class_name: 'Spree::Variant', optional: true
35
+ belongs_to :exchange_inventory_unit, class_name: 'Spree::InventoryUnit', inverse_of: :original_return_item, optional: true
36
+ belongs_to :customer_return, inverse_of: :return_items, optional: true
37
+ belongs_to :reimbursement, inverse_of: :return_items, optional: true
38
+ belongs_to :preferred_reimbursement_type, class_name: 'Spree::ReimbursementType', optional: true
39
+ belongs_to :override_reimbursement_type, class_name: 'Spree::ReimbursementType', optional: true
40
+ belongs_to :return_reason, class_name: 'Spree::ReturnReason', foreign_key: :return_reason_id, optional: true
41
41
 
42
42
  validate :eligible_exchange_variant
43
43
  validate :belongs_to_same_customer_order
@@ -77,22 +77,8 @@ module Spree
77
77
  before_create :set_default_amount, unless: :amount_changed?
78
78
  before_save :set_exchange_amount
79
79
 
80
- state_machine :reception_status, initial: :awaiting do
81
- after_transition to: COMPLETED_RECEPTION_STATUSES, do: :attempt_accept
82
- after_transition to: COMPLETED_RECEPTION_STATUSES, do: :check_unexchange
83
- after_transition to: :received, do: :process_inventory_unit!
84
-
85
- event(:cancel) { transition to: :cancelled, from: :awaiting }
86
-
87
- event(:receive) { transition to: :received, from: INTERMEDIATE_RECEPTION_STATUSES + [:awaiting] }
88
- event(:unexchange) { transition to: :unexchanged, from: [:awaiting] }
89
- event(:give) { transition to: :given_to_customer, from: :awaiting }
90
- event(:lost) { transition to: :lost_in_transit, from: :awaiting }
91
- event(:wrong_item_shipped) { transition to: :shipped_wrong_item, from: :awaiting }
92
- event(:short_shipped) { transition to: :short_shipped, from: :awaiting }
93
- event(:in_transit) { transition to: :in_transit, from: :awaiting }
94
- event(:expired) { transition to: :expired, from: :awaiting }
95
- end
80
+ include ::Spree::Config.state_machines.return_item_reception
81
+ include ::Spree::Config.state_machines.return_item_acceptance
96
82
 
97
83
  extend DisplayMoney
98
84
  money_methods :pre_tax_amount, :amount, :total, :total_excluding_vat
@@ -104,31 +90,6 @@ module Spree
104
90
  COMPLETED_RECEPTION_STATUSES.map(&:to_s).include?(reception_status.to_s)
105
91
  end
106
92
 
107
- state_machine :acceptance_status, initial: :pending do
108
- event :attempt_accept do
109
- transition to: :accepted, from: :accepted
110
- transition to: :accepted, from: :pending, if: ->(return_item) { return_item.eligible_for_return? }
111
- transition to: :manual_intervention_required, from: :pending, if: ->(return_item) { return_item.requires_manual_intervention? }
112
- transition to: :rejected, from: :pending
113
- end
114
-
115
- # bypasses eligibility checks
116
- event :accept do
117
- transition to: :accepted, from: [:accepted, :pending, :manual_intervention_required]
118
- end
119
-
120
- # bypasses eligibility checks
121
- event :reject do
122
- transition to: :rejected, from: [:accepted, :pending, :manual_intervention_required]
123
- end
124
-
125
- # bypasses eligibility checks
126
- event :require_manual_intervention do
127
- transition to: :manual_intervention_required, from: [:accepted, :pending, :manual_intervention_required]
128
- end
129
-
130
- after_transition any => any, do: :persist_acceptance_status_errors
131
- end
132
93
 
133
94
  attr_accessor :skip_customer_return_processing
134
95
 
@@ -214,7 +175,7 @@ module Spree
214
175
  event_paths.delete(:expired)
215
176
  event_paths.delete(:unexchange)
216
177
 
217
- status_paths.map{ |s| I18n.t("spree.reception_states.#{s}", default: s.to_s.humanize) }.zip(event_paths)
178
+ status_paths.map{ |status| I18n.t("spree.reception_states.#{status}", default: status.to_s.humanize) }.zip(event_paths)
218
179
  end
219
180
 
220
181
  def part_of_exchange?
@@ -226,7 +187,7 @@ module Spree
226
187
  private
227
188
 
228
189
  def persist_acceptance_status_errors
229
- update_attributes(acceptance_status_errors: validator.errors)
190
+ update(acceptance_status_errors: validator.errors)
230
191
  end
231
192
 
232
193
  def currency
@@ -3,8 +3,8 @@
3
3
  module Spree
4
4
  class RoleUser < Spree::Base
5
5
  self.table_name = "spree_roles_users"
6
- belongs_to :role, class_name: "Spree::Role"
7
- belongs_to :user, class_name: Spree::UserClassHandle.new
6
+ belongs_to :role, class_name: "Spree::Role", optional: true
7
+ belongs_to :user, class_name: Spree::UserClassHandle.new, optional: true
8
8
 
9
9
  after_create :auto_generate_spree_api_key
10
10
 
@@ -4,8 +4,8 @@ module Spree
4
4
  # An order's planned shipments including tracking and cost.
5
5
  #
6
6
  class Shipment < Spree::Base
7
- belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments
8
- belongs_to :stock_location, class_name: 'Spree::StockLocation'
7
+ belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments, optional: true
8
+ belongs_to :stock_location, class_name: 'Spree::StockLocation', optional: true
9
9
 
10
10
  has_many :adjustments, as: :adjustable, inverse_of: :adjustable, dependent: :delete_all
11
11
  has_many :inventory_units, dependent: :destroy, inverse_of: :shipment
@@ -31,7 +31,7 @@ module Spree
31
31
  scope :ready, -> { with_state('ready') }
32
32
  scope :shipped, -> { with_state('shipped') }
33
33
  scope :trackable, -> { where("tracking IS NOT NULL AND tracking != ''") }
34
- scope :with_state, ->(*s) { where(state: s) }
34
+ scope :with_state, ->(*state) { where(state: state) }
35
35
  # sort by most recent shipped_at, falling back to created_at. add "id desc" to make specs that involve this scope more deterministic.
36
36
  scope :reverse_chronological, -> {
37
37
  order(Arel.sql("coalesce(#{Spree::Shipment.table_name}.shipped_at, #{Spree::Shipment.table_name}.created_at) desc"), id: :desc)
@@ -39,41 +39,7 @@ module Spree
39
39
 
40
40
  scope :by_store, ->(store) { joins(:order).merge(Spree::Order.by_store(store)) }
41
41
 
42
- # shipment state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
43
- state_machine initial: :pending, use_transactions: false do
44
- event :ready do
45
- transition from: :pending, to: :shipped, if: :can_transition_from_pending_to_shipped?
46
- transition from: :pending, to: :ready, if: :can_transition_from_pending_to_ready?
47
- end
48
-
49
- event :pend do
50
- transition from: :ready, to: :pending
51
- end
52
-
53
- event :ship do
54
- transition from: [:ready, :canceled], to: :shipped
55
- end
56
- after_transition to: :shipped, do: :after_ship
57
-
58
- event :cancel do
59
- transition to: :canceled, from: [:pending, :ready]
60
- end
61
- after_transition to: :canceled, do: :after_cancel
62
-
63
- event :resume do
64
- transition from: :canceled, to: :ready, if: :can_transition_from_canceled_to_ready?
65
- transition from: :canceled, to: :pending
66
- end
67
- after_transition from: :canceled, to: [:pending, :ready, :shipped], do: :after_resume
68
-
69
- after_transition do |shipment, transition|
70
- shipment.state_changes.create!(
71
- previous_state: transition.from,
72
- next_state: transition.to,
73
- name: 'shipment'
74
- )
75
- end
76
- end
42
+ include ::Spree::Config.state_machines.shipment
77
43
 
78
44
  self.whitelisted_ransackable_associations = ['order']
79
45
  self.whitelisted_ransackable_attributes = ['number']
@@ -142,7 +108,7 @@ module Spree
142
108
  # @return [BigDecimal] the amount of this item, taking into consideration
143
109
  # all non-tax adjustments.
144
110
  def total_before_tax
145
- amount + adjustments.select { |a| !a.tax? && a.eligible? }.sum(&:amount)
111
+ amount + adjustments.select { |adjustment| !adjustment.tax? && adjustment.eligible? }.sum(&:amount)
146
112
  end
147
113
 
148
114
  # @return [BigDecimal] the amount of this shipment before VAT tax
@@ -219,7 +185,7 @@ module Spree
219
185
  def select_shipping_method(shipping_method)
220
186
  estimator = Spree::Config.stock.estimator_class.new
221
187
  rates = estimator.shipping_rates(to_package, false)
222
- rate = rates.detect { |r| r.shipping_method_id == shipping_method.id }
188
+ rate = rates.detect { |detected| detected.shipping_method_id == shipping_method.id }
223
189
  rate.selected = true
224
190
  self.shipping_rates = [rate]
225
191
  end
@@ -326,7 +292,7 @@ module Spree
326
292
 
327
293
  # Update Shipment and make sure Order states follow the shipment changes
328
294
  def update_attributes_and_order(params = {})
329
- if update_attributes params
295
+ if update(params)
330
296
  if params.key? :selected_shipping_rate_id
331
297
  # Changing the selected Shipping Rate won't update the cost (for now)
332
298
  # so we persist the Shipment#cost before running `order.recalculate`
@@ -2,10 +2,6 @@
2
2
 
3
3
  module Spree
4
4
  class ShippingCalculator < Calculator
5
- def compute_shipment(_shipment)
6
- raise NotImplementedError, "Please implement 'compute_shipment(shipment)' in your calculator: #{self.class.name}"
7
- end
8
-
9
5
  def compute_package(_package)
10
6
  raise NotImplementedError, "Please implement 'compute_package(package)' in your calculator: #{self.class.name}"
11
7
  end
@@ -21,9 +21,9 @@ class Spree::ShippingManifest
21
21
  states = {}
22
22
  units.group_by(&:state).each { |state, iu| states[state] = iu.count }
23
23
 
24
- line_item = units.first.line_item
25
- variant = units.first.variant
26
- ManifestItem.new(line_item, variant, units.length, states)
24
+ first_unit = units.first
25
+
26
+ ManifestItem.new(first_unit.line_item, first_unit.variant, units.length, states)
27
27
  end
28
28
  end.flatten
29
29
  end
@@ -28,7 +28,7 @@ module Spree
28
28
  has_many :shipping_method_zones, dependent: :destroy
29
29
  has_many :zones, through: :shipping_method_zones
30
30
 
31
- belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory'
31
+ belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory', optional: true
32
32
  has_many :shipping_method_stock_locations, dependent: :destroy, class_name: "Spree::ShippingMethodStockLocation"
33
33
  has_many :stock_locations, through: :shipping_method_stock_locations
34
34
 
@@ -41,7 +41,7 @@ module Spree
41
41
 
42
42
  scope :available_to_store, ->(store) do
43
43
  raise ArgumentError, "You must provide a store" if store.nil?
44
- store.shipping_methods.empty? ? all : where(id: store.shipping_method_ids)
44
+ store.shipping_methods.empty? ? all : where(id: store.shipping_methods.ids)
45
45
  end
46
46
 
47
47
  # @param shipping_category_ids [Array<Integer>] ids of desired shipping categories
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Spree
4
4
  class ShippingMethodCategory < Spree::Base
5
- belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
6
- belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
5
+ belongs_to :shipping_method, class_name: 'Spree::ShippingMethod', optional: true
6
+ belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories, optional: true
7
7
  end
8
8
  end