spree_core 3.0.10 → 3.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js.coffee.erb +12 -3
  3. data/app/helpers/spree/base_helper.rb +4 -1
  4. data/app/helpers/spree/products_helper.rb +37 -6
  5. data/app/mailers/spree/base_mailer.rb +11 -2
  6. data/app/models/concerns/spree/adjustment_source.rb +3 -10
  7. data/app/models/concerns/spree/default_price.rb +7 -1
  8. data/app/models/concerns/spree/named_type.rb +1 -1
  9. data/app/models/concerns/spree/user_api_authentication.rb +7 -1
  10. data/app/models/concerns/spree/user_methods.rb +47 -0
  11. data/app/models/concerns/spree/user_reporting.rb +2 -2
  12. data/app/models/concerns/spree/vat_price_calculation.rb +47 -0
  13. data/app/models/spree/address.rb +8 -7
  14. data/app/models/spree/adjustable/adjuster/base.rb +25 -0
  15. data/app/models/spree/adjustable/adjuster/promotion.rb +41 -0
  16. data/app/models/spree/adjustable/adjuster/tax.rb +26 -0
  17. data/app/models/spree/adjustable/adjustments_updater.rb +22 -45
  18. data/app/models/spree/adjustment.rb +8 -10
  19. data/app/models/spree/app_configuration.rb +5 -2
  20. data/app/models/spree/base.rb +4 -0
  21. data/app/models/spree/calculator.rb +0 -5
  22. data/app/models/spree/calculator/default_tax.rb +2 -10
  23. data/app/models/spree/classification.rb +7 -3
  24. data/app/models/spree/country.rb +14 -3
  25. data/app/models/spree/credit_card.rb +21 -31
  26. data/app/models/spree/customer_return.rb +7 -15
  27. data/app/models/spree/gateway.rb +7 -6
  28. data/app/models/spree/image.rb +1 -1
  29. data/app/models/spree/inventory_unit.rb +9 -6
  30. data/app/models/spree/legacy_user.rb +1 -6
  31. data/app/models/spree/line_item.rb +69 -68
  32. data/app/models/spree/log_entry.rb +1 -4
  33. data/app/models/spree/option_type.rb +15 -6
  34. data/app/models/spree/option_type_prototype.rb +9 -0
  35. data/app/models/spree/option_value.rb +11 -3
  36. data/app/models/spree/option_value_variant.rb +6 -0
  37. data/app/models/spree/order.rb +113 -64
  38. data/app/models/spree/order/checkout.rb +8 -11
  39. data/app/models/spree/order/currency_updater.rb +1 -1
  40. data/app/models/spree/order/store_credit.rb +96 -0
  41. data/app/models/spree/order_contents.rb +6 -1
  42. data/app/models/spree/order_inventory.rb +4 -8
  43. data/app/models/spree/order_promotion.rb +6 -0
  44. data/app/models/spree/order_updater.rb +2 -7
  45. data/app/models/spree/payment.rb +46 -19
  46. data/app/models/spree/payment/gateway_options.rb +8 -4
  47. data/app/models/spree/payment_method.rb +12 -13
  48. data/app/models/spree/payment_method/store_credit.rb +130 -0
  49. data/app/models/spree/preference.rb +1 -1
  50. data/app/models/spree/price.rb +16 -6
  51. data/app/models/spree/product.rb +52 -49
  52. data/app/models/spree/product/scopes.rb +7 -2
  53. data/app/models/spree/product_option_type.rb +7 -2
  54. data/app/models/spree/product_promotion_rule.rb +9 -0
  55. data/app/models/spree/product_property.rb +8 -10
  56. data/app/models/spree/promotion.rb +19 -19
  57. data/app/models/spree/promotion/rules/product.rb +3 -1
  58. data/app/models/spree/promotion/rules/taxon.rb +2 -1
  59. data/app/models/spree/promotion/rules/user.rb +4 -4
  60. data/app/models/spree/promotion_action.rb +3 -3
  61. data/app/models/spree/promotion_category.rb +1 -1
  62. data/app/models/spree/promotion_rule_taxon.rb +9 -0
  63. data/app/models/spree/promotion_rule_user.rb +9 -0
  64. data/app/models/spree/property.rb +2 -1
  65. data/app/models/spree/property_prototype.rb +9 -0
  66. data/app/models/spree/prototype.rb +8 -3
  67. data/app/models/spree/prototype_taxon.rb +9 -0
  68. data/app/models/spree/refund.rb +10 -7
  69. data/app/models/spree/refund_reason.rb +1 -1
  70. data/app/models/spree/reimbursement.rb +12 -16
  71. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +23 -6
  72. data/app/models/spree/reimbursement_type/store_credit.rb +28 -0
  73. data/app/models/spree/return_authorization.rb +8 -13
  74. data/app/models/spree/return_authorization_reason.rb +1 -1
  75. data/app/models/spree/return_item.rb +13 -12
  76. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +1 -1
  77. data/app/models/spree/role.rb +3 -2
  78. data/app/models/spree/role_user.rb +6 -0
  79. data/app/models/spree/shipment.rb +18 -23
  80. data/app/models/spree/shipment_handler.rb +2 -2
  81. data/app/models/spree/shipping_category.rb +6 -3
  82. data/app/models/spree/shipping_method.rb +11 -10
  83. data/app/models/spree/shipping_method_zone.rb +6 -0
  84. data/app/models/spree/shipping_rate.rb +16 -29
  85. data/app/models/spree/state.rb +3 -2
  86. data/app/models/spree/state_change.rb +1 -1
  87. data/app/models/spree/stock/content_item.rb +10 -12
  88. data/app/models/spree/stock/coordinator.rb +13 -14
  89. data/app/models/spree/stock/estimator.rb +28 -30
  90. data/app/models/spree/stock/inventory_unit_builder.rb +1 -9
  91. data/app/models/spree/stock/packer.rb +1 -1
  92. data/app/models/spree/stock/quantifier.rb +5 -5
  93. data/app/models/spree/stock/splitter/backordered.rb +2 -2
  94. data/app/models/spree/stock_item.rb +12 -18
  95. data/app/models/spree/stock_location.rb +4 -7
  96. data/app/models/spree/stock_movement.rb +11 -9
  97. data/app/models/spree/stock_transfer.rb +11 -12
  98. data/app/models/spree/store.rb +14 -6
  99. data/app/models/spree/store_credit.rb +252 -0
  100. data/app/models/spree/store_credit_category.rb +22 -0
  101. data/app/models/spree/store_credit_event.rb +38 -0
  102. data/app/models/spree/store_credit_type.rb +6 -0
  103. data/app/models/spree/tax_category.rb +3 -8
  104. data/app/models/spree/tax_rate.rb +56 -122
  105. data/app/models/spree/taxon.rb +11 -5
  106. data/app/models/spree/tracker.rb +12 -1
  107. data/app/models/spree/validations/db_maximum_length_validator.rb +2 -1
  108. data/app/models/spree/variant.rb +82 -50
  109. data/app/models/spree/zone.rb +21 -17
  110. data/app/models/spree/zone_member.rb +6 -0
  111. data/app/validators/db_maximum_length_validator.rb +11 -0
  112. data/app/views/layouts/spree/base_mailer.html.erb +38 -781
  113. data/app/views/spree/order_mailer/_adjustment.html.erb +8 -0
  114. data/app/views/spree/order_mailer/_subtotal.html.erb +8 -0
  115. data/app/views/spree/order_mailer/_total.html.erb +8 -0
  116. data/app/views/spree/order_mailer/cancel_email.html.erb +13 -28
  117. data/app/views/spree/order_mailer/cancel_email.text.erb +1 -1
  118. data/app/views/spree/order_mailer/confirm_email.html.erb +49 -63
  119. data/app/views/spree/order_mailer/confirm_email.text.erb +1 -1
  120. data/app/views/spree/shared/_base_mailer_header.html.erb +5 -7
  121. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +777 -0
  122. data/app/views/spree/shared/_error_messages.html.erb +1 -1
  123. data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
  124. data/app/views/spree/shipment_mailer/shipped_email.html.erb +21 -14
  125. data/app/views/spree/shipment_mailer/shipped_email.text.erb +3 -3
  126. data/config/initializers/user_class_extensions.rb +7 -38
  127. data/config/locales/en.yml +113 -13
  128. data/config/routes.rb +7 -0
  129. data/db/default/spree/default_reimbursement_type.rb +1 -1
  130. data/db/default/spree/zones.rb +4 -5
  131. data/db/migrate/20150118210639_create_spree_store_credits.rb +24 -0
  132. data/db/migrate/20150118211500_create_spree_store_credit_categories.rb +8 -0
  133. data/db/migrate/20150118212051_create_spree_store_credit_events.rb +17 -0
  134. data/db/migrate/20150118212101_create_spree_store_credit_types.rb +10 -0
  135. data/db/migrate/20150314013438_add_missing_indexes.rb +25 -0
  136. data/db/migrate/20150317174308_remove_duplicated_indexes_from_multi_columns.rb +18 -0
  137. data/db/migrate/20150324104002_remove_user_index_from_spree_state_changes.rb +14 -0
  138. data/db/migrate/20150522071831_add_position_to_spree_payment_methods.rb +5 -0
  139. data/db/migrate/20150626181949_add_taxable_adjustment_total_to_line_item.rb +19 -0
  140. data/db/migrate/20150627090949_migrate_payment_methods_display.rb +12 -0
  141. data/db/migrate/20150714154102_spree_payment_method_store_credits.rb +12 -0
  142. data/db/migrate/20150726141425_rename_has_and_belongs_to_associations_to_model_names.rb +18 -0
  143. data/db/migrate/20150727191614_spree_store_credit_types.rb +11 -0
  144. data/db/migrate/20150819154308_add_discontinued_to_products_and_variants.rb +68 -0
  145. data/db/migrate/20151220072838_remove_shipping_method_id_from_spree_orders.rb +13 -0
  146. data/db/migrate/20160207191757_add_id_column_to_earlier_habtm_tables.rb +16 -0
  147. data/db/migrate/20160219165458_add_indexes.rb +14 -0
  148. data/lib/generators/spree/dummy/templates/rails/database.yml +31 -24
  149. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -1
  150. data/lib/spree/core.rb +16 -0
  151. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  152. data/lib/spree/core/controller_helpers/common.rb +3 -3
  153. data/lib/spree/core/controller_helpers/order.rb +6 -5
  154. data/lib/spree/core/controller_helpers/search.rb +1 -1
  155. data/lib/spree/core/controller_helpers/store.rb +29 -0
  156. data/lib/spree/core/delegate_belongs_to.rb +2 -2
  157. data/lib/spree/core/engine.rb +30 -25
  158. data/lib/spree/core/environment.rb +1 -1
  159. data/lib/spree/core/importer/order.rb +37 -40
  160. data/lib/spree/core/number_generator.rb +52 -0
  161. data/lib/spree/core/product_filters.rb +1 -1
  162. data/lib/spree/core/search/base.rb +4 -3
  163. data/lib/spree/core/version.rb +1 -1
  164. data/lib/spree/localized_number.rb +3 -1
  165. data/lib/spree/permitted_attributes.rb +5 -2
  166. data/lib/spree/testing_support/common_rake.rb +3 -3
  167. data/lib/spree/testing_support/factories.rb +3 -3
  168. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/country_factory.rb +2 -2
  170. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  171. data/lib/spree/testing_support/factories/payment_factory.rb +5 -0
  172. data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -0
  173. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +5 -0
  174. data/lib/spree/testing_support/factories/refund_factory.rb +9 -1
  175. data/lib/spree/testing_support/factories/return_authorization_factory.rb +2 -0
  176. data/lib/spree/testing_support/factories/state_factory.rb +2 -2
  177. data/lib/spree/testing_support/factories/store_credit_category_factory.rb +9 -0
  178. data/lib/spree/testing_support/factories/store_credit_event_factory.rb +8 -0
  179. data/lib/spree/testing_support/factories/store_credit_factory.rb +17 -0
  180. data/lib/spree/testing_support/factories/store_credit_type_factory.rb +11 -0
  181. data/lib/spree/testing_support/factories/user_factory.rb +1 -1
  182. data/lib/spree/testing_support/factories/zone_member_factory.rb +6 -0
  183. data/lib/spree/testing_support/microdata.rb +189 -0
  184. data/lib/tasks/core.rake +68 -0
  185. data/lib/tasks/exchanges.rake +2 -2
  186. data/spec/fixtures/microdata.html +22 -0
  187. data/spec/fixtures/microdata_itemref.html +15 -0
  188. data/spec/fixtures/microdata_no_itemscope.html +20 -0
  189. data/spec/helpers/base_helper_spec.rb +64 -1
  190. data/spec/helpers/products_helper_spec.rb +75 -3
  191. data/spec/lib/i18n_spec.rb +2 -2
  192. data/spec/lib/search/base_spec.rb +2 -2
  193. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +4 -2
  194. data/spec/lib/spree/core/controller_helpers/store_spec.rb +56 -0
  195. data/spec/lib/spree/core/importer/order_spec.rb +226 -123
  196. data/spec/lib/spree/core/number_generator_spec.rb +175 -0
  197. data/spec/lib/spree/core_spec.rb +23 -0
  198. data/spec/lib/spree/localized_number_spec.rb +10 -0
  199. data/spec/mailers/order_mailer_spec.rb +11 -13
  200. data/spec/mailers/shipment_mailer_spec.rb +26 -8
  201. data/spec/mailers/test_mailer_spec.rb +15 -1
  202. data/spec/models/option_type_prototype_spec.rb +9 -0
  203. data/spec/models/spree/ability_spec.rb +6 -13
  204. data/spec/models/spree/address_spec.rb +1 -1
  205. data/spec/models/spree/adjustable/adjuster/base_spec.rb +10 -0
  206. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +211 -0
  207. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +86 -0
  208. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +2 -262
  209. data/spec/models/spree/adjustment_spec.rb +27 -1
  210. data/spec/models/spree/app_configuration_spec.rb +5 -2
  211. data/spec/models/spree/calculator/default_tax_spec.rb +39 -14
  212. data/spec/models/spree/concerns/user_methods_spec.rb +55 -0
  213. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +66 -0
  214. data/spec/models/spree/country_spec.rb +45 -8
  215. data/spec/models/spree/credit_card_spec.rb +8 -8
  216. data/spec/models/spree/customer_return_spec.rb +4 -26
  217. data/spec/models/spree/gateway_spec.rb +7 -0
  218. data/spec/models/spree/image_spec.rb +3 -0
  219. data/spec/models/spree/inventory_unit_spec.rb +1 -18
  220. data/spec/models/spree/line_item_spec.rb +78 -18
  221. data/spec/models/spree/option_type_spec.rb +2 -2
  222. data/spec/models/spree/option_value_spec.rb +8 -3
  223. data/spec/models/spree/order/checkout_spec.rb +49 -39
  224. data/spec/models/spree/order/currency_updater_spec.rb +3 -3
  225. data/spec/models/spree/order/finalizing_spec.rb +0 -3
  226. data/spec/models/spree/order/payment_spec.rb +1 -1
  227. data/spec/models/spree/order/state_machine_spec.rb +1 -6
  228. data/spec/models/spree/order/store_credit_spec.rb +423 -0
  229. data/spec/models/spree/order/updating_spec.rb +2 -2
  230. data/spec/models/spree/order_contents_spec.rb +42 -1
  231. data/spec/models/spree/order_inventory_spec.rb +27 -17
  232. data/spec/models/spree/order_spec.rb +65 -52
  233. data/spec/models/spree/payment/gateway_options_spec.rb +10 -2
  234. data/spec/models/spree/payment/store_credit_spec.rb +60 -0
  235. data/spec/models/spree/payment_method/store_credit_spec.rb +291 -0
  236. data/spec/models/spree/payment_method_spec.rb +22 -14
  237. data/spec/models/spree/payment_spec.rb +37 -44
  238. data/spec/models/spree/price_spec.rb +86 -0
  239. data/spec/models/spree/product/scopes_spec.rb +35 -0
  240. data/spec/models/spree/product_option_type_spec.rb +6 -2
  241. data/spec/models/spree/product_promotion_rule_spec.rb +9 -0
  242. data/spec/models/spree/product_property_spec.rb +11 -0
  243. data/spec/models/spree/product_spec.rb +82 -15
  244. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +1 -1
  245. data/spec/models/spree/promotion/rules/user_spec.rb +8 -0
  246. data/spec/models/spree/promotion_action_spec.rb +1 -1
  247. data/spec/models/spree/promotion_rule_spec.rb +1 -1
  248. data/spec/models/spree/promotion_rule_taxon_spec.rb +9 -0
  249. data/spec/models/spree/promotion_rule_user_spec.rb +9 -0
  250. data/spec/models/spree/promotion_spec.rb +57 -36
  251. data/spec/models/spree/property_prototype_spec.rb +9 -0
  252. data/spec/models/spree/prototype_taxon_spec.rb +9 -0
  253. data/spec/models/spree/refund_reason_spec.rb +7 -0
  254. data/spec/models/spree/reimbursement_spec.rb +3 -30
  255. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +17 -5
  256. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +101 -0
  257. data/spec/models/spree/return_authorization_reason_spec.rb +7 -0
  258. data/spec/models/spree/return_authorization_spec.rb +2 -22
  259. data/spec/models/spree/return_item_spec.rb +50 -1
  260. data/spec/models/spree/returns_calculator_spec.rb +1 -1
  261. data/spec/models/spree/role_spec.rb +7 -0
  262. data/spec/models/spree/shipment_spec.rb +17 -17
  263. data/spec/models/spree/shipping_calculator_spec.rb +2 -2
  264. data/spec/models/spree/shipping_category_spec.rb +14 -0
  265. data/spec/models/spree/shipping_method_spec.rb +9 -2
  266. data/spec/models/spree/shipping_rate_spec.rb +40 -41
  267. data/spec/models/spree/state_spec.rb +12 -1
  268. data/spec/models/spree/stock/content_item_spec.rb +9 -0
  269. data/spec/models/spree/stock/estimator_spec.rb +56 -8
  270. data/spec/models/spree/stock/quantifier_spec.rb +61 -32
  271. data/spec/models/spree/stock_item_spec.rb +19 -1
  272. data/spec/models/spree/store_credit_event_spec.rb +101 -0
  273. data/spec/models/spree/store_credit_spec.rb +786 -0
  274. data/spec/models/spree/store_spec.rb +39 -11
  275. data/spec/models/spree/tax_category_spec.rb +6 -1
  276. data/spec/models/spree/tax_rate_spec.rb +204 -44
  277. data/spec/models/spree/user_spec.rb +105 -38
  278. data/spec/models/spree/variant_spec.rb +281 -9
  279. data/spec/models/spree/zone_member_spec.rb +38 -0
  280. data/spec/models/spree/zone_spec.rb +32 -8
  281. data/spec/spec_helper.rb +3 -0
  282. data/spec/support/concerns/{adjustment_source_spec.rb → adjustment_source.rb} +0 -0
  283. data/spec/support/concerns/{default_price_spec.rb → default_price.rb} +9 -0
  284. data/spec/validators/db_maximum_length_validator_spec.rb +22 -0
  285. data/spree_core.gemspec +5 -6
  286. metadata +99 -36
  287. data/CHANGELOG.md +0 -4
  288. data/app/models/concerns/spree/number_generator.rb +0 -39
  289. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +0 -24
@@ -74,6 +74,9 @@ module Spree
74
74
  transition to: :awaiting_return
75
75
  end
76
76
 
77
+ before_transition to: :complete, do: :ensure_line_item_variants_are_not_discontinued
78
+ before_transition to: :complete, do: :ensure_line_items_are_in_stock
79
+
77
80
  if states[:payment]
78
81
  before_transition to: :complete do |order|
79
82
  if order.payment_required? && order.payments.valid.empty?
@@ -86,12 +89,12 @@ module Spree
86
89
  after_transition to: :complete, do: :persist_user_credit_card
87
90
  before_transition to: :payment, do: :set_shipments_cost
88
91
  before_transition to: :payment, do: :create_tax_charge!
89
- before_transition to: :payment, do: :assign_default_credit_card
90
92
  end
91
93
 
92
94
  before_transition from: :cart, do: :ensure_line_items_present
93
95
 
94
96
  if states[:address]
97
+ before_transition from: :address, do: :update_line_item_prices!
95
98
  before_transition from: :address, do: :create_tax_charge!
96
99
  before_transition to: :address, do: :assign_default_addresses!
97
100
  before_transition from: :address, do: :persist_user_address!
@@ -104,12 +107,9 @@ module Spree
104
107
  before_transition from: :delivery, do: :apply_free_shipping_promotions
105
108
  end
106
109
 
107
- before_transition to: :resumed, do: :ensure_line_item_variants_are_not_deleted
110
+ before_transition to: :resumed, do: :ensure_line_item_variants_are_not_discontinued
108
111
  before_transition to: :resumed, do: :ensure_line_items_are_in_stock
109
112
 
110
- before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
111
- before_transition to: :complete, do: :ensure_line_items_are_in_stock
112
-
113
113
  after_transition to: :complete, do: :finalize!
114
114
  after_transition to: :resumed, do: :after_resume
115
115
  after_transition to: :canceled, do: :after_cancel
@@ -282,15 +282,12 @@ module Spree
282
282
 
283
283
  def persist_user_credit_card
284
284
  if !temporary_credit_card && user_id && valid_credit_cards.present?
285
- default_cc = valid_credit_cards.first
286
- default_cc.user_id = user_id
287
- default_cc.default = true
288
- default_cc.save
285
+ valid_credit_cards.first.update(user_id: user_id, default: true)
289
286
  end
290
287
  end
291
288
 
292
289
  def assign_default_credit_card
293
- if payments.from_credit_card.count == 0 && user_has_valid_default_card? && payment_required?
290
+ if payments.from_credit_card.size == 0 && user_has_valid_default_card? && payment_required?
294
291
  cc = user.default_credit_card
295
292
  payments.create!(payment_method_id: cc.payment_method_id, source: cc, amount: total)
296
293
  end
@@ -329,7 +326,7 @@ module Spree
329
326
  if @updating_params[:order] && (@updating_params[:order][:payments_attributes] ||
330
327
  @updating_params[:order][:existing_card])
331
328
  @updating_params[:order][:payments_attributes] ||= [{}]
332
- @updating_params[:order][:payments_attributes].first[:amount] = total
329
+ @updating_params[:order][:payments_attributes].first[:amount] = order_total_after_store_credit
333
330
  end
334
331
  end
335
332
  end
@@ -7,7 +7,7 @@ module Spree
7
7
 
8
8
  def homogenize_line_item_currencies
9
9
  update_line_item_currencies!
10
- update!
10
+ update_with_updater!
11
11
  end
12
12
 
13
13
  end
@@ -0,0 +1,96 @@
1
+ module Spree
2
+ class Order < Spree::Base
3
+ module StoreCredit
4
+ def add_store_credit_payments
5
+ payments.store_credits.where(state: 'checkout').map(&:invalidate!)
6
+
7
+ remaining_total = outstanding_balance
8
+
9
+ if user && user.store_credits.any?
10
+ payment_method = Spree::PaymentMethod::StoreCredit.available.first
11
+ raise "Store credit payment method could not be found" unless payment_method
12
+
13
+ user.store_credits.order_by_priority.each do |credit|
14
+ break if remaining_total.zero?
15
+ next if credit.amount_remaining.zero?
16
+
17
+ amount_to_take = store_credit_amount(credit, remaining_total)
18
+ create_store_credit_payment(payment_method, credit, amount_to_take)
19
+ remaining_total -= amount_to_take
20
+ end
21
+ end
22
+ end
23
+
24
+ def covered_by_store_credit?
25
+ return false unless user
26
+ user.total_available_store_credit >= total
27
+ end
28
+ alias_method :covered_by_store_credit, :covered_by_store_credit?
29
+
30
+ def total_available_store_credit
31
+ return 0.0 unless user
32
+ user.total_available_store_credit
33
+ end
34
+
35
+ def could_use_store_credit?
36
+ total_available_store_credit > 0
37
+ end
38
+
39
+ def order_total_after_store_credit
40
+ total - total_applicable_store_credit
41
+ end
42
+
43
+ def total_applicable_store_credit
44
+ if payment? || confirm? || complete?
45
+ total_applied_store_credit
46
+ else
47
+ [total, (user.try(:total_available_store_credit) || 0.0)].min
48
+ end
49
+ end
50
+
51
+ def total_applied_store_credit
52
+ payments.store_credits.valid.sum(:amount)
53
+ end
54
+
55
+ def using_store_credit?
56
+ total_applied_store_credit > 0
57
+ end
58
+
59
+ def display_total_applicable_store_credit
60
+ Spree::Money.new(-total_applicable_store_credit, currency: currency)
61
+ end
62
+
63
+ def display_total_applied_store_credit
64
+ Spree::Money.new(-total_applied_store_credit, currency: currency)
65
+ end
66
+
67
+ def display_order_total_after_store_credit
68
+ Spree::Money.new(order_total_after_store_credit, currency: currency)
69
+ end
70
+
71
+ def display_total_available_store_credit
72
+ Spree::Money.new(total_available_store_credit, currency: currency)
73
+ end
74
+
75
+ def display_store_credit_remaining_after_capture
76
+ Spree::Money.new(total_available_store_credit - total_applicable_store_credit, currency: currency)
77
+ end
78
+
79
+ private
80
+
81
+ def create_store_credit_payment(payment_method, credit, amount)
82
+ payments.create!(
83
+ source: credit,
84
+ payment_method: payment_method,
85
+ amount: amount,
86
+ state: 'checkout',
87
+ response_code: credit.generate_authorization_code
88
+ )
89
+ end
90
+
91
+ def store_credit_amount(credit, total)
92
+ [credit.amount_remaining, total].min
93
+ end
94
+ end
95
+ end
96
+ end
@@ -7,7 +7,7 @@ module Spree
7
7
  end
8
8
 
9
9
  def add(variant, quantity = 1, options = {})
10
- timestamp = Time.now
10
+ timestamp = Time.current
11
11
  line_item = add_to_line_item(variant, quantity, options)
12
12
  options[:line_item_created] = true if timestamp <= line_item.created_at
13
13
  after_add_or_remove(line_item, options)
@@ -18,6 +18,11 @@ module Spree
18
18
  after_add_or_remove(line_item, options)
19
19
  end
20
20
 
21
+ def remove_line_item(line_item, options = {})
22
+ line_item.destroy!
23
+ after_add_or_remove(line_item, options)
24
+ end
25
+
21
26
  def update_cart(params)
22
27
  if order.update_attributes(filter_order_items(params))
23
28
  order.line_items = order.line_items.select { |li| li.quantity > 0 }
@@ -8,6 +8,8 @@ module Spree
8
8
  @variant = line_item.variant
9
9
  end
10
10
 
11
+ delegate :inventory_units, to: :line_item
12
+
11
13
  # Only verify inventory for completed orders (as orders in frontend checkout
12
14
  # have inventory assigned via +order.create_proposed_shipment+) or when
13
15
  # shipment is explicitly passed
@@ -29,10 +31,6 @@ module Spree
29
31
  end
30
32
  end
31
33
 
32
- def inventory_units
33
- line_item.inventory_units
34
- end
35
-
36
34
  private
37
35
  def remove(item_units, shipment = nil)
38
36
  quantity = item_units.size - line_item.quantity
@@ -82,9 +80,7 @@ module Spree
82
80
  def remove_from_shipment(shipment, quantity)
83
81
  return 0 if quantity == 0 || shipment.shipped?
84
82
 
85
- shipment_units = shipment.inventory_units_for_item(line_item, variant).reject do |variant_unit|
86
- variant_unit.state == 'shipped'
87
- end.sort_by(&:state)
83
+ shipment_units = shipment.inventory_units_for_item(line_item, variant).reject(&:shipped?).sort_by(&:state)
88
84
 
89
85
  removed_quantity = 0
90
86
 
@@ -94,7 +90,7 @@ module Spree
94
90
  removed_quantity += 1
95
91
  end
96
92
 
97
- shipment.destroy if shipment.inventory_units.count == 0
93
+ shipment.destroy if shipment.inventory_units.count.zero?
98
94
 
99
95
  # removing this from shipment, and adding to stock_location
100
96
  if order.completed?
@@ -0,0 +1,6 @@
1
+ module Spree
2
+ class OrderPromotion < Spree::Base
3
+ belongs_to :order, class_name: 'Spree::Order'
4
+ belongs_to :promotion, class_name: 'Spree::Promotion'
5
+ end
6
+ end
@@ -110,7 +110,7 @@ module Spree
110
110
  shipment_total: order.shipment_total,
111
111
  promo_total: order.promo_total,
112
112
  total: order.total,
113
- updated_at: Time.now,
113
+ updated_at: Time.current,
114
114
  )
115
115
  end
116
116
 
@@ -161,7 +161,7 @@ module Spree
161
161
  last_state = order.payment_state
162
162
  if payments.present? && payments.valid.size == 0
163
163
  order.payment_state = 'failed'
164
- elsif order.state == 'canceled' && order.payment_total == 0
164
+ elsif order.canceled? && order.payment_total == 0
165
165
  order.payment_state = 'void'
166
166
  else
167
167
  order.payment_state = 'balance_due' if order.outstanding_balance > 0
@@ -171,10 +171,5 @@ module Spree
171
171
  order.state_changed('payment') if last_state != order.payment_state
172
172
  order.payment_state
173
173
  end
174
-
175
- private
176
- def round_money(n)
177
- (n * 100).round / 100.0
178
- end
179
174
  end
180
175
  end
@@ -1,24 +1,21 @@
1
1
  module Spree
2
2
  class Payment < Spree::Base
3
+ include Spree::Core::NumberGenerator.new(prefix: 'P', letters: true, length: 7)
4
+
3
5
  extend FriendlyId
4
6
  friendly_id :number, slug_column: :number, use: :slugged
5
7
 
6
8
  include Spree::Payment::Processing
7
- include Spree::NumberGenerator
8
-
9
- def generate_number(options = {})
10
- options[:prefix] ||= 'P'
11
- options[:letters] ||= true
12
- options[:length] ||= 7
13
- super(options)
14
- end
15
9
 
16
10
  NON_RISKY_AVS_CODES = ['B', 'D', 'H', 'J', 'M', 'Q', 'T', 'V', 'X', 'Y'].freeze
17
11
  RISKY_AVS_CODES = ['A', 'C', 'E', 'F', 'G', 'I', 'K', 'L', 'N', 'O', 'P', 'R', 'S', 'U', 'W', 'Z'].freeze
12
+ INVALID_STATES = %w(failed invalid).freeze
18
13
 
19
- belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :payments
14
+ with_options inverse_of: :payments do
15
+ belongs_to :order, class_name: 'Spree::Order', touch: true
16
+ belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
17
+ end
20
18
  belongs_to :source, polymorphic: true
21
- belongs_to :payment_method, class_name: 'Spree::PaymentMethod', inverse_of: :payments
22
19
 
23
20
  has_many :offsets, -> { offset_payment }, class_name: "Spree::Payment", foreign_key: :source_id
24
21
  has_many :log_entries, as: :source
@@ -26,7 +23,7 @@ module Spree
26
23
  has_many :capture_events, class_name: 'Spree::PaymentCaptureEvent'
27
24
  has_many :refunds, inverse_of: :payment
28
25
 
29
- validates_presence_of :payment_method
26
+ validates :payment_method, presence: true
30
27
  before_validation :validate_source
31
28
 
32
29
  after_save :create_payment_profile, if: :profiles_supported?
@@ -36,6 +33,7 @@ module Spree
36
33
 
37
34
  # invalidate previously entered payments
38
35
  after_create :invalidate_old_payments
36
+ after_create :create_eligible_credit_event
39
37
 
40
38
  attr_accessor :source_attributes, :request_env
41
39
 
@@ -43,7 +41,8 @@ module Spree
43
41
 
44
42
  validates :amount, numericality: true
45
43
 
46
- default_scope { order("#{self.table_name}.created_at") }
44
+ delegate :store_credit?, to: :payment_method, allow_nil: true
45
+ default_scope { order(:created_at) }
47
46
 
48
47
  scope :from_credit_card, -> { where(source_type: 'Spree::CreditCard') }
49
48
  scope :with_state, ->(s) { where(state: s.to_s) }
@@ -57,13 +56,18 @@ module Spree
57
56
  scope :failed, -> { with_state('failed') }
58
57
 
59
58
  scope :risky, -> { where("avs_response IN (?) OR (cvv_response_code IS NOT NULL and cvv_response_code != 'M') OR state = 'failed'", RISKY_AVS_CODES) }
60
- scope :valid, -> { where.not(state: %w(failed invalid)) }
59
+ scope :valid, -> { where.not(state: INVALID_STATES) }
60
+
61
+ scope :store_credits, -> { where(source_type: Spree::StoreCredit.to_s) }
62
+ scope :not_store_credits, -> { where(arel_table[:source_type].not_eq(Spree::StoreCredit.to_s).or(arel_table[:source_type].eq(nil))) }
61
63
 
62
64
  # transaction_id is much easier to understand
63
65
  def transaction_id
64
66
  response_code
65
67
  end
66
68
 
69
+ delegate :currency, to: :order
70
+
67
71
  # order state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
68
72
  state_machine initial: :checkout do
69
73
  # With card payments, happens before purchase or authorization happens
@@ -103,10 +107,6 @@ module Spree
103
107
  end
104
108
  end
105
109
 
106
- def currency
107
- order.currency
108
- end
109
-
110
110
  def money
111
111
  Spree::Money.new(amount, { currency: currency })
112
112
  end
@@ -180,6 +180,10 @@ module Spree
180
180
 
181
181
  private
182
182
 
183
+ def has_invalid_state?
184
+ INVALID_STATES.include?(state)
185
+ end
186
+
183
187
  def validate_source
184
188
  if source && !source.valid?
185
189
  source.errors.each do |field, error|
@@ -196,7 +200,7 @@ module Spree
196
200
 
197
201
  def create_payment_profile
198
202
  # Don't attempt to create on bad payments.
199
- return if %w(invalid failed).include?(state)
203
+ return if has_invalid_state?
200
204
  # Payment profile cannot be created without source
201
205
  return unless source
202
206
  # Imported payments shouldn't create a payment profile.
@@ -208,7 +212,7 @@ module Spree
208
212
  end
209
213
 
210
214
  def invalidate_old_payments
211
- if state != 'invalid' and state != 'failed'
215
+ unless has_invalid_state?
212
216
  order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
213
217
  payment.invalidate!
214
218
  end
@@ -245,5 +249,28 @@ module Spree
245
249
  end
246
250
  end
247
251
 
252
+ def create_eligible_credit_event
253
+ # When cancelling an order, a payment with the negative amount
254
+ # of the payment total is created to refund the customer. That
255
+ # payment has a source of itself (Spree::Payment) no matter the
256
+ # type of payment getting refunded, hence the additional check
257
+ # if the source is a store credit.
258
+ return unless store_credit? && source.is_a?(Spree::StoreCredit)
259
+
260
+ # creates the store credit event
261
+ source.update_attributes!({
262
+ action: Spree::StoreCredit::ELIGIBLE_ACTION,
263
+ action_amount: amount,
264
+ action_authorization_code: response_code,
265
+ })
266
+ end
267
+
268
+ def invalidate_old_payments
269
+ return if store_credit? # store credits shouldn't invalidate other payment types
270
+ order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
271
+ payment.invalidate! unless payment.store_credit?
272
+ end
273
+ end
274
+
248
275
  end
249
276
  end
@@ -26,19 +26,19 @@ module Spree
26
26
  end
27
27
 
28
28
  def shipping
29
- order.ship_total * 100
29
+ order.ship_total * exchange_multiplier
30
30
  end
31
31
 
32
32
  def tax
33
- order.additional_tax_total * 100
33
+ order.additional_tax_total * exchange_multiplier
34
34
  end
35
35
 
36
36
  def subtotal
37
- order.item_total * 100
37
+ order.item_total * exchange_multiplier
38
38
  end
39
39
 
40
40
  def discount
41
- order.promo_total * 100
41
+ order.promo_total * exchange_multiplier
42
42
  end
43
43
 
44
44
  def currency
@@ -81,6 +81,10 @@ module Spree
81
81
  def order
82
82
  @payment.order
83
83
  end
84
+
85
+ def exchange_multiplier
86
+ @payment.payment_method.try(:exchange_multiplier) || 1.0
87
+ end
84
88
  end
85
89
  end
86
90
  end