spree_core 2.3.13 → 2.4.0.rc1

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 (232) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js.coffee.erb +1 -5
  3. data/app/helpers/spree/base_helper.rb +22 -11
  4. data/app/helpers/spree/products_helper.rb +8 -7
  5. data/app/mailers/spree/base_mailer.rb +1 -0
  6. data/app/mailers/spree/reimbursement_mailer.rb +10 -0
  7. data/app/mailers/spree/test_mailer.rb +2 -3
  8. data/app/models/concerns/spree/adjustment_source.rb +24 -0
  9. data/app/models/concerns/spree/calculated_adjustments.rb +33 -0
  10. data/app/models/concerns/spree/named_type.rb +12 -0
  11. data/app/models/concerns/spree/user_address.rb +30 -0
  12. data/app/models/concerns/spree/user_payment_source.rb +19 -0
  13. data/app/models/spree/address.rb +13 -6
  14. data/app/models/spree/adjustment.rb +5 -5
  15. data/app/models/spree/app_configuration.rb +8 -4
  16. data/app/models/spree/asset.rb +1 -1
  17. data/app/models/spree/base.rb +0 -3
  18. data/app/models/spree/calculator/flat_rate.rb +1 -5
  19. data/app/models/spree/calculator/returns/default_refund_amount.rb +36 -0
  20. data/app/models/spree/classification.rb +1 -1
  21. data/app/models/spree/credit_card.rb +18 -22
  22. data/app/models/spree/customer_return.rb +70 -0
  23. data/app/models/spree/exchange.rb +42 -0
  24. data/app/models/spree/gateway/bogus.rb +3 -3
  25. data/app/models/spree/image.rb +1 -1
  26. data/app/models/spree/inventory_unit.rb +32 -8
  27. data/app/models/spree/item_adjustments.rb +7 -11
  28. data/app/models/spree/legacy_user.rb +2 -2
  29. data/app/models/spree/line_item.rb +25 -12
  30. data/app/models/spree/option_type.rb +1 -1
  31. data/app/models/spree/option_value.rb +1 -8
  32. data/app/models/spree/order.rb +163 -145
  33. data/app/models/spree/order/checkout.rb +35 -23
  34. data/app/models/spree/order/payments.rb +66 -0
  35. data/app/models/spree/order_contents.rb +34 -24
  36. data/app/models/spree/order_populator.rb +6 -4
  37. data/app/models/spree/order_updater.rb +10 -1
  38. data/app/models/spree/payment.rb +19 -16
  39. data/app/models/spree/payment/processing.rb +40 -72
  40. data/app/models/spree/payment_method.rb +1 -1
  41. data/app/models/spree/payment_method/check.rb +0 -2
  42. data/app/models/spree/preference.rb +1 -1
  43. data/app/models/spree/preferences/preferable.rb +20 -0
  44. data/app/models/spree/price.rb +13 -3
  45. data/app/models/spree/product.rb +24 -29
  46. data/app/models/spree/product_property.rb +0 -2
  47. data/app/models/spree/promotion.rb +66 -24
  48. data/app/models/spree/promotion/actions/create_adjustment.rb +2 -2
  49. data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -11
  50. data/app/models/spree/promotion/actions/create_line_items.rb +2 -12
  51. data/app/models/spree/promotion/rules/first_order.rb +6 -2
  52. data/app/models/spree/promotion/rules/item_total.rb +42 -4
  53. data/app/models/spree/promotion/rules/one_use_per_user.rb +24 -0
  54. data/app/models/spree/promotion/rules/product.rb +13 -11
  55. data/app/models/spree/promotion/rules/taxon.rb +61 -0
  56. data/app/models/spree/promotion/rules/user.rb +1 -1
  57. data/app/models/spree/promotion/rules/user_logged_in.rb +4 -1
  58. data/app/models/spree/promotion_category.rb +6 -0
  59. data/app/models/spree/promotion_handler/cart.rb +14 -18
  60. data/app/models/spree/promotion_handler/coupon.rb +25 -16
  61. data/app/models/spree/promotion_rule.rb +13 -0
  62. data/app/models/spree/property.rb +1 -3
  63. data/app/models/spree/refund.rb +91 -0
  64. data/app/models/spree/refund_reason.rb +13 -0
  65. data/app/models/spree/reimbursement.rb +148 -0
  66. data/app/models/spree/reimbursement/credit.rb +25 -0
  67. data/app/models/spree/reimbursement/reimbursement_type_engine.rb +56 -0
  68. data/app/models/spree/reimbursement/reimbursement_type_validator.rb +12 -0
  69. data/app/models/spree/reimbursement_performer.rb +43 -0
  70. data/app/models/spree/reimbursement_tax_calculator.rb +38 -0
  71. data/app/models/spree/reimbursement_type.rb +16 -0
  72. data/app/models/spree/reimbursement_type/credit.rb +13 -0
  73. data/app/models/spree/reimbursement_type/exchange.rb +9 -0
  74. data/app/models/spree/reimbursement_type/original_payment.rb +13 -0
  75. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +50 -0
  76. data/app/models/spree/return_authorization.rb +52 -68
  77. data/app/models/spree/return_authorization_reason.rb +7 -0
  78. data/app/models/spree/return_item.rb +230 -0
  79. data/app/models/spree/return_item/default_eligibility_validator.rb +27 -0
  80. data/app/models/spree/return_item/eligibility_validator/base_validator.rb +24 -0
  81. data/app/models/spree/return_item/eligibility_validator/rma_required.rb +17 -0
  82. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +16 -0
  83. data/app/models/spree/return_item/exchange_variant_eligibility/same_option_value.rb +34 -0
  84. data/app/models/spree/return_item/exchange_variant_eligibility/same_product.rb +10 -0
  85. data/app/models/spree/returns_calculator.rb +8 -0
  86. data/app/models/spree/shipment.rb +209 -154
  87. data/app/models/spree/shipment_handler.rb +43 -0
  88. data/app/models/spree/shipping_calculator.rb +1 -1
  89. data/app/models/spree/shipping_category.rb +2 -2
  90. data/app/models/spree/shipping_method.rb +1 -1
  91. data/app/models/spree/shipping_method_category.rb +1 -1
  92. data/app/models/spree/shipping_rate.rb +4 -0
  93. data/app/models/spree/stock/adjuster.rb +10 -11
  94. data/app/models/spree/stock/availability_validator.rb +6 -10
  95. data/app/models/spree/stock/content_item.rb +48 -0
  96. data/app/models/spree/stock/coordinator.rb +14 -7
  97. data/app/models/spree/stock/estimator.rb +1 -1
  98. data/app/models/spree/stock/inventory_unit_builder.rb +21 -0
  99. data/app/models/spree/stock/package.rb +38 -51
  100. data/app/models/spree/stock/packer.rb +13 -11
  101. data/app/models/spree/stock/prioritizer.rb +7 -7
  102. data/app/models/spree/stock/splitter/base.rb +2 -2
  103. data/app/models/spree/stock_item.rb +6 -9
  104. data/app/models/spree/stock_location.rb +17 -25
  105. data/app/models/spree/stock_movement.rb +1 -8
  106. data/app/models/spree/stock_transfer.rb +0 -2
  107. data/app/models/spree/store.rb +1 -1
  108. data/app/models/spree/tax_category.rb +2 -2
  109. data/app/models/spree/tax_rate.rb +16 -22
  110. data/app/models/spree/taxon.rb +1 -1
  111. data/app/models/spree/variant.rb +45 -23
  112. data/app/models/spree/zone.rb +17 -17
  113. data/app/models/spree/zone_member.rb +1 -1
  114. data/app/views/layouts/spree/base_mailer.html.erb +784 -0
  115. data/app/views/spree/order_mailer/cancel_email.html.erb +45 -0
  116. data/app/views/spree/order_mailer/cancel_email.text.erb +2 -2
  117. data/app/views/spree/order_mailer/confirm_email.html.erb +84 -0
  118. data/app/views/spree/order_mailer/confirm_email.text.erb +2 -2
  119. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +22 -0
  120. data/app/views/spree/shared/_base_mailer_footer.html.erb +20 -0
  121. data/app/views/spree/shared/_base_mailer_header.html.erb +31 -0
  122. data/app/views/spree/shipment_mailer/shipped_email.html.erb +34 -0
  123. data/app/views/spree/test_mailer/test_email.html.erb +40 -0
  124. data/app/views/spree/test_mailer/test_email.text.erb +2 -2
  125. data/config/initializers/friendly_id.rb +88 -0
  126. data/config/initializers/premailer_assets.rb +1 -0
  127. data/config/initializers/user_class_extensions.rb +9 -22
  128. data/config/locales/en.yml +180 -12
  129. data/db/default/spree/states.rb +73 -55
  130. data/db/migrate/20130213191427_create_default_stock.rb +1 -0
  131. data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -5
  132. data/db/migrate/20140309033438_create_store_from_preferences.rb +0 -7
  133. data/db/migrate/20140318191500_create_spree_taxons_promotion_rules.rb +8 -0
  134. data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +1 -1
  135. data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +5 -3
  136. data/db/migrate/20140625214618_create_spree_refunds.rb +12 -0
  137. data/db/migrate/20140702140656_create_spree_return_authorization_inventory_unit.rb +12 -0
  138. data/db/migrate/20140707125621_rename_return_authorization_inventory_unit_to_return_items.rb +5 -0
  139. data/db/migrate/20140709160534_backfill_line_item_pre_tax_amount.rb +10 -0
  140. data/db/migrate/20140710041921_recreate_spree_return_authorizations.rb +55 -0
  141. data/db/migrate/20140710181204_add_amount_fields_to_return_items.rb +7 -0
  142. data/db/migrate/20140710190048_drop_return_authorization_amount.rb +5 -0
  143. data/db/migrate/20140713140455_create_spree_return_authorization_reasons.rb +28 -0
  144. data/db/migrate/20140713140527_create_spree_refund_reasons.rb +14 -0
  145. data/db/migrate/20140713142214_rename_return_authorization_reason.rb +5 -0
  146. data/db/migrate/20140715182625_create_spree_promotion_categories.rb +11 -0
  147. data/db/migrate/20140716204111_drop_received_at_on_return_items.rb +9 -0
  148. data/db/migrate/20140716212330_add_reception_and_acceptance_status_to_return_items.rb +6 -0
  149. data/db/migrate/20140717155155_create_default_refund_reason.rb +9 -0
  150. data/db/migrate/20140717185932_add_default_to_spree_stock_locations.rb +5 -0
  151. data/db/migrate/20140718133010_create_spree_customer_returns.rb +9 -0
  152. data/db/migrate/20140718133349_add_customer_return_id_to_return_item.rb +6 -0
  153. data/db/migrate/20140718195325_create_friendly_id_slugs.rb +15 -0
  154. data/db/migrate/20140723004419_rename_spree_refund_return_authorization_id.rb +5 -0
  155. data/db/migrate/20140723152808_increase_return_item_pre_tax_amount_precision.rb +13 -0
  156. data/db/migrate/20140723214541_copy_product_slugs_to_slug_history.rb +15 -0
  157. data/db/migrate/20140725131539_create_spree_reimbursements.rb +21 -0
  158. data/db/migrate/20140728225422_add_promotionable_to_spree_products.rb +5 -0
  159. data/db/migrate/20140729133613_add_exchange_inventory_unit_foreign_keys.rb +7 -0
  160. data/db/migrate/20140730155938_add_acceptance_status_errors_to_return_item.rb +5 -0
  161. data/db/migrate/20140731150017_create_spree_reimbursement_types.rb +20 -0
  162. data/db/migrate/20140805171035_add_default_to_spree_credit_cards.rb +5 -0
  163. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +10 -0
  164. data/db/migrate/20140806144901_add_type_to_reimbursement_type.rb +9 -0
  165. data/db/migrate/20140808184039_create_spree_reimbursement_credits.rb +10 -0
  166. data/db/migrate/20140827170513_add_meta_title_to_spree_products.rb +7 -0
  167. data/db/migrate/20140924164824_add_code_to_spree_tax_categories.rb +5 -0
  168. data/db/migrate/20141002191113_add_code_to_spree_shipping_methods.rb +5 -0
  169. data/db/migrate/20141007230328_add_cancel_audit_fields_to_spree_orders.rb +6 -0
  170. data/db/migrate/20141009204607_add_store_id_to_orders.rb +8 -0
  171. data/lib/generators/spree/install/install_generator.rb +7 -3
  172. data/lib/spree/core.rb +11 -10
  173. data/lib/spree/core/controller_helpers/common.rb +3 -10
  174. data/lib/spree/core/controller_helpers/order.rb +15 -12
  175. data/lib/spree/core/controller_helpers/strong_parameters.rb +9 -9
  176. data/lib/spree/core/engine.rb +8 -1
  177. data/lib/spree/core/importer/order.rb +5 -17
  178. data/lib/spree/core/search/base.rb +1 -1
  179. data/lib/spree/core/validators/email.rb +1 -1
  180. data/lib/spree/core/version.rb +1 -1
  181. data/lib/spree/instrumentation.rb +41 -0
  182. data/lib/spree/migrations.rb +3 -7
  183. data/lib/spree/money.rb +2 -2
  184. data/lib/spree/permitted_attributes.rb +10 -9
  185. data/lib/spree/testing_support/ability_helpers.rb +25 -25
  186. data/lib/spree/testing_support/authorization_helpers.rb +3 -5
  187. data/lib/spree/testing_support/capybara_ext.rb +2 -2
  188. data/lib/spree/testing_support/factories/calculator_factory.rb +0 -8
  189. data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
  190. data/lib/spree/testing_support/factories/customer_return_factory.rb +31 -0
  191. data/lib/spree/testing_support/factories/inventory_unit_factory.rb +1 -0
  192. data/lib/spree/testing_support/factories/line_item_factory.rb +2 -1
  193. data/lib/spree/testing_support/factories/order_factory.rb +11 -6
  194. data/lib/spree/testing_support/factories/promotion_category_factory.rb +6 -0
  195. data/lib/spree/testing_support/factories/promotion_factory.rb +9 -7
  196. data/lib/spree/testing_support/factories/refund_factory.rb +14 -0
  197. data/lib/spree/testing_support/factories/reimbursement_factory.rb +16 -0
  198. data/lib/spree/testing_support/factories/reimbursement_type_factory.rb +7 -0
  199. data/lib/spree/testing_support/factories/return_authorization_factory.rb +9 -3
  200. data/lib/spree/testing_support/factories/return_item_factory.rb +10 -0
  201. data/lib/spree/testing_support/factories/shipment_factory.rb +1 -0
  202. data/lib/spree/testing_support/factories/shipping_method_factory.rb +3 -2
  203. data/lib/spree/testing_support/factories/stock_factory.rb +12 -11
  204. data/lib/spree/testing_support/flash.rb +2 -2
  205. data/lib/tasks/email.rake +7 -0
  206. data/lib/tasks/exchanges.rake +70 -0
  207. data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
  208. data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
  209. data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
  210. data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
  211. data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
  212. data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
  213. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
  214. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
  215. data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
  216. data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
  217. data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
  218. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
  219. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
  220. metadata +163 -47
  221. data/app/models/concerns/spree/ransackable_attributes.rb +0 -19
  222. data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +0 -5
  223. data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +0 -13
  224. data/db/migrate/20141105213646_update_classifications_positions.rb +0 -9
  225. data/db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb +0 -5
  226. data/db/migrate/20150515211137_fix_adjustment_order_id.rb +0 -70
  227. data/lib/spree/core/adjustment_source.rb +0 -26
  228. data/lib/spree/core/calculated_adjustments.rb +0 -35
  229. data/lib/spree/core/controller_helpers.rb +0 -20
  230. data/lib/spree/core/user_address.rb +0 -32
  231. data/lib/spree/core/user_payment_source.rb +0 -20
  232. data/lib/spree/localized_number.rb +0 -20
@@ -0,0 +1,36 @@
1
+ require_dependency 'spree/returns_calculator'
2
+
3
+ module Spree
4
+ module Calculator::Returns
5
+ class DefaultRefundAmount < ReturnsCalculator
6
+
7
+ def self.description
8
+ Spree.t(:default_refund_amount)
9
+ end
10
+
11
+ def compute(return_item)
12
+ return 0.0.to_d if return_item.exchange_requested?
13
+ weighted_order_adjustment_amount(return_item.inventory_unit) + weighted_line_item_pre_tax_amount(return_item.inventory_unit)
14
+ end
15
+
16
+ private
17
+
18
+ def weighted_order_adjustment_amount(inventory_unit)
19
+ inventory_unit.order.adjustments.eligible.non_tax.sum(:amount) * percentage_of_order_total(inventory_unit)
20
+ end
21
+
22
+ def weighted_line_item_pre_tax_amount(inventory_unit)
23
+ inventory_unit.line_item.pre_tax_amount * percentage_of_line_item(inventory_unit)
24
+ end
25
+
26
+ def percentage_of_order_total(inventory_unit)
27
+ return 0.0 if inventory_unit.order.pre_tax_item_amount.zero?
28
+ weighted_line_item_pre_tax_amount(inventory_unit) / inventory_unit.order.pre_tax_item_amount
29
+ end
30
+
31
+ def percentage_of_line_item(inventory_unit)
32
+ 1 / BigDecimal.new(inventory_unit.line_item.quantity)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Classification < Spree::Base
3
3
  self.table_name = 'spree_products_taxons'
4
- acts_as_list scope: :taxon
4
+ acts_as_list
5
5
  belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications
6
6
  belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications
7
7
 
@@ -1,9 +1,12 @@
1
1
  module Spree
2
2
  class CreditCard < Spree::Base
3
3
  belongs_to :payment_method
4
+ belongs_to :user, class_name: Spree.user_class, foreign_key: 'user_id'
4
5
  has_many :payments, as: :source
5
6
 
6
- before_create :set_missing_info
7
+ before_save :set_last_digits
8
+
9
+ after_save :ensure_one_default
7
10
 
8
11
  attr_accessor :encrypted_data,
9
12
  :number,
@@ -18,6 +21,7 @@ module Spree
18
21
  validate :expiry_not_in_the_past
19
22
 
20
23
  scope :with_payment_profile, -> { where('gateway_customer_profile_id IS NOT NULL') }
24
+ scope :default, -> { where(default: true) }
21
25
 
22
26
  # needed for some of the ActiveMerchant gateways (eg. SagePay)
23
27
  alias_attribute :brand, :cc_type
@@ -35,7 +39,7 @@ module Spree
35
39
  return unless expiry.present?
36
40
 
37
41
  self[:month], self[:year] =
38
- if expiry.match(/\d\s?\/\s?\d/) # will match mm/yy and mm / yyyy
42
+ if expiry.match(/\d{2}\s?\/\s?\d{2,4}/) # will match mm/yy and mm / yyyy
39
43
  expiry.delete(' ').split('/')
40
44
  elsif match = expiry.match(/(\d{2})(\d{2,4})/) # will match mmyy and mmyyyy
41
45
  [match[1], match[2]]
@@ -44,7 +48,7 @@ module Spree
44
48
  self[:year] = "20" + self[:year] if self[:year].length == 2
45
49
  self[:year] = self[:year].to_i
46
50
  end
47
- self[:month] = self[:month].to_i
51
+ self[:month] = self[:month].to_i if self[:month]
48
52
  end
49
53
 
50
54
  def number=(num)
@@ -63,6 +67,12 @@ module Spree
63
67
  end
64
68
  end
65
69
 
70
+ def set_last_digits
71
+ number.to_s.gsub!(/\s/,'')
72
+ verification_value.to_s.gsub!(/\s/,'')
73
+ self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
74
+ end
75
+
66
76
  def try_type_from_number
67
77
  numbers = number.delete(' ') if number
68
78
  CARD_TYPES.find{|type, pattern| return type.to_s if numbers =~ pattern}.to_s
@@ -94,9 +104,7 @@ module Spree
94
104
  # Indicates whether its possible to credit the payment. Note that most gateways require that the
95
105
  # payment be settled first which generally happens within 12-24 hours of the transaction.
96
106
  def can_credit?(payment)
97
- return false unless payment.completed?
98
- return false unless payment.order.payment_state == 'credit_owed'
99
- payment.credit_allowed > 0
107
+ payment.completed? && payment.credit_allowed > 0
100
108
  end
101
109
 
102
110
  def has_payment_profile?
@@ -144,24 +152,12 @@ module Spree
144
152
  !self.encrypted_data.present? && !self.has_payment_profile?
145
153
  end
146
154
 
147
- def set_last_digits
148
- number.to_s.gsub!(/\s/,'')
149
- verification_value.to_s.gsub!(/\s/,'')
150
- self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
151
- end
152
-
153
- def set_missing_info
154
- set_last_digits
155
- if has_payment_profile?
156
- if matching_card = self.class.where(gateway_customer_profile_id: self.gateway_customer_profile_id, gateway_payment_profile_id: self.gateway_payment_profile_id).first
157
- self.cc_type = matching_card.cc_type
158
- self.last_digits = matching_card.last_digits
159
- self.month = matching_card.month
160
- self.name = matching_card.name
161
- self.year = matching_card.year
155
+ def ensure_one_default
156
+ if self.user_id && self.default
157
+ CreditCard.where(default: true).where.not(id: self.id).where(user_id: self.user_id).each do |ucc|
158
+ ucc.update_columns(default: false)
162
159
  end
163
160
  end
164
161
  end
165
-
166
162
  end
167
163
  end
@@ -0,0 +1,70 @@
1
+ module Spree
2
+ class CustomerReturn < Spree::Base
3
+ belongs_to :stock_location
4
+
5
+ has_many :return_items, inverse_of: :customer_return
6
+ has_many :return_authorizations, through: :return_items
7
+ has_many :reimbursements, inverse_of: :customer_return
8
+
9
+ after_create :process_return!
10
+ before_create :generate_number
11
+
12
+ validates :return_items, presence: true
13
+ validates :stock_location, presence: true
14
+ validate :return_items_belong_to_same_order
15
+
16
+ accepts_nested_attributes_for :return_items
17
+
18
+ def pre_tax_total
19
+ return_items.sum(:pre_tax_amount)
20
+ end
21
+
22
+ def display_pre_tax_total
23
+ Spree::Money.new(pre_tax_total, { currency: Spree::Config[:currency] })
24
+ end
25
+
26
+ # Temporarily tie a customer_return to one order
27
+ def order
28
+ return nil if return_items.blank?
29
+ return_items.first.inventory_unit.order
30
+ end
31
+
32
+ def order_id
33
+ order.try(:id)
34
+ end
35
+
36
+ def fully_reimbursed?
37
+ completely_decided? && return_items.accepted.includes(:reimbursement).all? { |return_item| return_item.reimbursement.try(:reimbursed?) }
38
+ end
39
+
40
+ def completely_decided?
41
+ !return_items.undecided.exists?
42
+ end
43
+
44
+ private
45
+
46
+ def generate_number
47
+ self.number ||= loop do
48
+ random = "CR#{Array.new(9){rand(9)}.join}"
49
+ break random unless self.class.exists?(number: random)
50
+ end
51
+ end
52
+
53
+ def process_return!
54
+ return_items.each(&:receive!)
55
+ order.return! if order.all_inventory_units_returned?
56
+ end
57
+
58
+ def return_items_belong_to_same_order
59
+ if return_items.select{ |return_item| return_item.inventory_unit.order_id != order_id }.any?
60
+ errors.add(:base, Spree.t(:return_items_cannot_be_associated_with_multiple_orders))
61
+ end
62
+ end
63
+
64
+ def inventory_units
65
+ return_items.flat_map(&:inventory_unit)
66
+ end
67
+
68
+ end
69
+ end
70
+
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ class Exchange
3
+
4
+ def initialize(order, reimbursement_objects)
5
+ @order = order
6
+ @reimbursement_objects = reimbursement_objects
7
+ end
8
+
9
+ def description
10
+ @reimbursement_objects.map do |reimbursement_object|
11
+ "#{reimbursement_object.variant.options_text} => #{reimbursement_object.exchange_variant.options_text}"
12
+ end.join(" | ")
13
+ end
14
+
15
+ def display_amount
16
+ Spree::Money.new @reimbursement_objects.map(&:total).sum
17
+ end
18
+
19
+ def perform!
20
+ shipments = Spree::Stock::Coordinator.new(@order, @reimbursement_objects.map(&:build_exchange_inventory_unit)).shipments
21
+ @order.shipments += shipments
22
+ @order.save!
23
+ shipments.each do |shipment|
24
+ shipment.update!(@order)
25
+ shipment.finalize!
26
+ end
27
+ end
28
+
29
+ def to_key
30
+ nil
31
+ end
32
+
33
+ def self.param_key
34
+ "spree_exchange"
35
+ end
36
+
37
+ def self.model_name
38
+ Spree::Exchange
39
+ end
40
+
41
+ end
42
+ end
@@ -18,10 +18,10 @@ module Spree
18
18
  end
19
19
 
20
20
  def create_profile(payment)
21
+ return if payment.source.has_payment_profile?
21
22
  # simulate the storage of credit card profile using remote service
22
- if success = VALID_CCS.include?(payment.source.number)
23
- payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
24
- end
23
+ success = VALID_CCS.include? payment.source.number
24
+ payment.source.update_attributes(:gateway_customer_profile_id => generate_profile_id(success))
25
25
  end
26
26
 
27
27
  def authorize(money, credit_card, options = {})
@@ -33,7 +33,7 @@ module Spree
33
33
  # if there are errors from the plugin, then add a more meaningful message
34
34
  def no_attachment_errors
35
35
  unless attachment.errors.empty?
36
- # uncomment this to get rid of the less-than-useful interrim messages
36
+ # uncomment this to get rid of the less-than-useful interim messages
37
37
  # errors.clear
38
38
  errors.add :attachment, "Paperclip returned errors for file '#{attachment_file_name}' - check ImageMagick installation or image source file."
39
39
  false
@@ -3,11 +3,16 @@ module Spree
3
3
  belongs_to :variant, class_name: "Spree::Variant", inverse_of: :inventory_units
4
4
  belongs_to :order, class_name: "Spree::Order", inverse_of: :inventory_units
5
5
  belongs_to :shipment, class_name: "Spree::Shipment", touch: true, inverse_of: :inventory_units
6
- belongs_to :return_authorization, class_name: "Spree::ReturnAuthorization", inverse_of: :inventory_units
6
+ belongs_to :return_authorization, class_name: "Spree::ReturnAuthorization"
7
7
  belongs_to :line_item, class_name: "Spree::LineItem", inverse_of: :inventory_units
8
8
 
9
+ has_many :return_items, inverse_of: :inventory_unit
10
+ has_one :original_return_item, class_name: "Spree::ReturnItem", foreign_key: :exchange_inventory_unit_id
11
+
9
12
  scope :backordered, -> { where state: 'backordered' }
13
+ scope :on_hand, -> { where state: 'on_hand' }
10
14
  scope :shipped, -> { where state: 'shipped' }
15
+ scope :returned, -> { where state: 'returned' }
11
16
  scope :backordered_per_variant, ->(stock_item) do
12
17
  includes(:shipment, :order)
13
18
  .where("spree_shipments.state != 'canceled'").references(:shipment)
@@ -21,7 +26,7 @@ module Spree
21
26
  event :fill_backorder do
22
27
  transition to: :on_hand, from: :backordered
23
28
  end
24
- after_transition on: :fill_backorder, do: :fulfill_order
29
+ after_transition on: :fill_backorder, do: :update_order
25
30
 
26
31
  event :ship do
27
32
  transition to: :shipped, if: :allow_ship?
@@ -33,8 +38,8 @@ module Spree
33
38
  end
34
39
 
35
40
  # This was refactored from a simpler query because the previous implementation
36
- # lead to issues once users tried to modify the objects returned. That's due
37
- # to ActiveRecord `joins(shipment: :stock_location)` only return readonly
41
+ # led to issues once users tried to modify the objects returned. That's due
42
+ # to ActiveRecord `joins(shipment: :stock_location)` only returning readonly
38
43
  # objects
39
44
  #
40
45
  # Returns an array of backordered inventory units as per a given stock item
@@ -63,16 +68,35 @@ module Spree
63
68
  Spree::Variant.unscoped { super }
64
69
  end
65
70
 
71
+ def current_or_new_return_item
72
+ Spree::ReturnItem.from_inventory_unit(self)
73
+ end
74
+
75
+ def additional_tax_total
76
+ line_item.additional_tax_total * percentage_of_line_item
77
+ end
78
+
79
+ def included_tax_total
80
+ line_item.included_tax_total * percentage_of_line_item
81
+ end
82
+
66
83
  private
67
84
 
68
85
  def allow_ship?
69
- Spree::Config[:allow_backorder_shipping] || self.on_hand?
86
+ self.on_hand?
70
87
  end
71
88
 
72
- def fulfill_order
89
+ def update_order
73
90
  self.reload
74
- order.fulfill!
91
+ order.update!
92
+ end
93
+
94
+ def percentage_of_line_item
95
+ 1 / BigDecimal.new(line_item.quantity)
96
+ end
97
+
98
+ def current_return_item
99
+ return_items.not_cancelled.first
75
100
  end
76
101
  end
77
102
  end
78
-
@@ -9,9 +9,8 @@ module Spree
9
9
 
10
10
  def initialize(item)
11
11
  @item = item
12
-
13
12
  # Don't attempt to reload the item from the DB if it's not there
14
- @item.reload if @item.instance_of?(Shipment) && @item.persisted?
13
+ @item.reload if @item.persisted?
15
14
  end
16
15
 
17
16
  def update
@@ -28,20 +27,17 @@ module Spree
28
27
  #
29
28
  # It also fits the criteria for sales tax as outlined here:
30
29
  # http://www.boe.ca.gov/formspubs/pub113/
31
- #
30
+ #
32
31
  # Tax adjustments come in not one but *two* exciting flavours:
33
32
  # Included & additional
34
33
 
35
34
  # Included tax adjustments are those which are included in the price.
36
- # These ones should not effect the eventual total price.
35
+ # These ones should not affect the eventual total price.
37
36
  #
38
- # Additional tax adjustments are the opposite; effecting the final total.
37
+ # Additional tax adjustments are the opposite, affecting the final total.
39
38
  promo_total = 0
40
39
  run_callbacks :promo_adjustments do
41
- promotion_total = adjustments.promotion.reload.map do |adjustment|
42
- adjustment.update!(@item)
43
- end.compact.sum
44
-
40
+ promotion_total = adjustments.promotion.reload.map(&:update!).compact.sum
45
41
  unless promotion_total == 0
46
42
  choose_best_promotion_adjustment
47
43
  end
@@ -52,7 +48,7 @@ module Spree
52
48
  additional_tax_total = 0
53
49
  run_callbacks :tax_adjustments do
54
50
  tax = (item.respond_to?(:all_adjustments) ? item.all_adjustments : item.adjustments).tax
55
- included_tax_total = tax.is_included.reload.map(&:update!).compact.sum
51
+ included_tax_total = tax.included.reload.map(&:update!).compact.sum
56
52
  additional_tax_total = tax.additional.reload.map(&:update!).compact.sum
57
53
  end
58
54
 
@@ -70,7 +66,7 @@ module Spree
70
66
  # have the same amount, then it will pick the latest one.
71
67
  def choose_best_promotion_adjustment
72
68
  if best_promotion_adjustment
73
- other_promotions = self.adjustments.promotion.where("id NOT IN (?)", best_promotion_adjustment.id)
69
+ other_promotions = self.adjustments.promotion.where.not(id: best_promotion_adjustment.id)
74
70
  other_promotions.update_all(:eligible => false)
75
71
  end
76
72
  end
@@ -1,8 +1,8 @@
1
1
  # Default implementation of User. This class is intended to be modified by extensions (ex. spree_auth_devise)
2
2
  module Spree
3
3
  class LegacyUser < Spree::Base
4
- include Core::UserAddress
5
- include Core::UserPaymentSource
4
+ include UserAddress
5
+ include UserPaymentSource
6
6
 
7
7
  self.table_name = 'spree_users'
8
8
 
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class LineItem < Spree::Base
3
- before_validation :adjust_quantity
3
+ before_validation :invalid_quantity_check
4
4
  belongs_to :order, class_name: "Spree::Order", inverse_of: :line_items, touch: true
5
5
  belongs_to :variant, class_name: "Spree::Variant", inverse_of: :line_items
6
6
  belongs_to :tax_category, class_name: "Spree::TaxCategory"
@@ -24,7 +24,6 @@ module Spree
24
24
 
25
25
  validate :ensure_proper_currency
26
26
  before_destroy :update_inventory
27
- before_destroy :destroy_inventory_units
28
27
 
29
28
  after_save :update_inventory
30
29
  after_save :update_adjustments
@@ -35,9 +34,6 @@ module Spree
35
34
 
36
35
  attr_accessor :target_shipment
37
36
 
38
- self.whitelisted_ransackable_associations = ['variant']
39
- self.whitelisted_ransackable_attributes = ['variant_id']
40
-
41
37
  def copy_price
42
38
  if variant
43
39
  self.price = variant.price if price.nil?
@@ -61,8 +57,12 @@ module Spree
61
57
  amount + promo_total
62
58
  end
63
59
 
60
+ def discounted_money
61
+ Spree::Money.new(discounted_amount, { currency: currency })
62
+ end
63
+
64
64
  def final_amount
65
- amount + adjustment_total.to_f
65
+ amount + adjustment_total
66
66
  end
67
67
  alias total final_amount
68
68
 
@@ -77,7 +77,7 @@ module Spree
77
77
  alias display_total money
78
78
  alias display_amount money
79
79
 
80
- def adjust_quantity
80
+ def invalid_quantity_check
81
81
  self.quantity = 0 if quantity.nil? || quantity < 0
82
82
  end
83
83
 
@@ -99,6 +99,23 @@ module Spree
99
99
  Spree::Variant.unscoped { super }
100
100
  end
101
101
 
102
+ def options=(options={})
103
+ opts = options.dup # we will be deleting from the hash, so leave the caller's copy intact
104
+
105
+ currency = opts.delete(:currency) || order.try(:currency)
106
+
107
+ if currency
108
+ self.currency = currency
109
+ self.price = variant.price_in(currency).amount +
110
+ variant.price_modifier_amount_in(currency, opts)
111
+ else
112
+ self.price = variant.price +
113
+ variant.price_modifier_amount(opts)
114
+ end
115
+
116
+ self.assign_attributes opts
117
+ end
118
+
102
119
  private
103
120
  def update_inventory
104
121
  if (changed? || target_shipment.present?) && self.order.has_checkout_step?("delivery")
@@ -106,13 +123,9 @@ module Spree
106
123
  end
107
124
  end
108
125
 
109
- def destroy_inventory_units
110
- inventory_units.destroy_all
111
- end
112
-
113
126
  def update_adjustments
114
127
  if quantity_changed?
115
- update_tax_charge # Called to ensure pre_tax_amount is updated.
128
+ update_tax_charge # Called to ensure pre_tax_amount is updated.
116
129
  recalculate_adjustments
117
130
  end
118
131
  end