spree_core 2.3.13 → 2.4.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree.js.coffee.erb +1 -5
- data/app/helpers/spree/base_helper.rb +22 -11
- data/app/helpers/spree/products_helper.rb +8 -7
- data/app/mailers/spree/base_mailer.rb +1 -0
- data/app/mailers/spree/reimbursement_mailer.rb +10 -0
- data/app/mailers/spree/test_mailer.rb +2 -3
- data/app/models/concerns/spree/adjustment_source.rb +24 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +33 -0
- data/app/models/concerns/spree/named_type.rb +12 -0
- data/app/models/concerns/spree/user_address.rb +30 -0
- data/app/models/concerns/spree/user_payment_source.rb +19 -0
- data/app/models/spree/address.rb +13 -6
- data/app/models/spree/adjustment.rb +5 -5
- data/app/models/spree/app_configuration.rb +8 -4
- data/app/models/spree/asset.rb +1 -1
- data/app/models/spree/base.rb +0 -3
- data/app/models/spree/calculator/flat_rate.rb +1 -5
- data/app/models/spree/calculator/returns/default_refund_amount.rb +36 -0
- data/app/models/spree/classification.rb +1 -1
- data/app/models/spree/credit_card.rb +18 -22
- data/app/models/spree/customer_return.rb +70 -0
- data/app/models/spree/exchange.rb +42 -0
- data/app/models/spree/gateway/bogus.rb +3 -3
- data/app/models/spree/image.rb +1 -1
- data/app/models/spree/inventory_unit.rb +32 -8
- data/app/models/spree/item_adjustments.rb +7 -11
- data/app/models/spree/legacy_user.rb +2 -2
- data/app/models/spree/line_item.rb +25 -12
- data/app/models/spree/option_type.rb +1 -1
- data/app/models/spree/option_value.rb +1 -8
- data/app/models/spree/order.rb +163 -145
- data/app/models/spree/order/checkout.rb +35 -23
- data/app/models/spree/order/payments.rb +66 -0
- data/app/models/spree/order_contents.rb +34 -24
- data/app/models/spree/order_populator.rb +6 -4
- data/app/models/spree/order_updater.rb +10 -1
- data/app/models/spree/payment.rb +19 -16
- data/app/models/spree/payment/processing.rb +40 -72
- data/app/models/spree/payment_method.rb +1 -1
- data/app/models/spree/payment_method/check.rb +0 -2
- data/app/models/spree/preference.rb +1 -1
- data/app/models/spree/preferences/preferable.rb +20 -0
- data/app/models/spree/price.rb +13 -3
- data/app/models/spree/product.rb +24 -29
- data/app/models/spree/product_property.rb +0 -2
- data/app/models/spree/promotion.rb +66 -24
- data/app/models/spree/promotion/actions/create_adjustment.rb +2 -2
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -11
- data/app/models/spree/promotion/actions/create_line_items.rb +2 -12
- data/app/models/spree/promotion/rules/first_order.rb +6 -2
- data/app/models/spree/promotion/rules/item_total.rb +42 -4
- data/app/models/spree/promotion/rules/one_use_per_user.rb +24 -0
- data/app/models/spree/promotion/rules/product.rb +13 -11
- data/app/models/spree/promotion/rules/taxon.rb +61 -0
- data/app/models/spree/promotion/rules/user.rb +1 -1
- data/app/models/spree/promotion/rules/user_logged_in.rb +4 -1
- data/app/models/spree/promotion_category.rb +6 -0
- data/app/models/spree/promotion_handler/cart.rb +14 -18
- data/app/models/spree/promotion_handler/coupon.rb +25 -16
- data/app/models/spree/promotion_rule.rb +13 -0
- data/app/models/spree/property.rb +1 -3
- data/app/models/spree/refund.rb +91 -0
- data/app/models/spree/refund_reason.rb +13 -0
- data/app/models/spree/reimbursement.rb +148 -0
- data/app/models/spree/reimbursement/credit.rb +25 -0
- data/app/models/spree/reimbursement/reimbursement_type_engine.rb +56 -0
- data/app/models/spree/reimbursement/reimbursement_type_validator.rb +12 -0
- data/app/models/spree/reimbursement_performer.rb +43 -0
- data/app/models/spree/reimbursement_tax_calculator.rb +38 -0
- data/app/models/spree/reimbursement_type.rb +16 -0
- data/app/models/spree/reimbursement_type/credit.rb +13 -0
- data/app/models/spree/reimbursement_type/exchange.rb +9 -0
- data/app/models/spree/reimbursement_type/original_payment.rb +13 -0
- data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +50 -0
- data/app/models/spree/return_authorization.rb +52 -68
- data/app/models/spree/return_authorization_reason.rb +7 -0
- data/app/models/spree/return_item.rb +230 -0
- data/app/models/spree/return_item/default_eligibility_validator.rb +27 -0
- data/app/models/spree/return_item/eligibility_validator/base_validator.rb +24 -0
- data/app/models/spree/return_item/eligibility_validator/rma_required.rb +17 -0
- data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +16 -0
- data/app/models/spree/return_item/exchange_variant_eligibility/same_option_value.rb +34 -0
- data/app/models/spree/return_item/exchange_variant_eligibility/same_product.rb +10 -0
- data/app/models/spree/returns_calculator.rb +8 -0
- data/app/models/spree/shipment.rb +209 -154
- data/app/models/spree/shipment_handler.rb +43 -0
- data/app/models/spree/shipping_calculator.rb +1 -1
- data/app/models/spree/shipping_category.rb +2 -2
- data/app/models/spree/shipping_method.rb +1 -1
- data/app/models/spree/shipping_method_category.rb +1 -1
- data/app/models/spree/shipping_rate.rb +4 -0
- data/app/models/spree/stock/adjuster.rb +10 -11
- data/app/models/spree/stock/availability_validator.rb +6 -10
- data/app/models/spree/stock/content_item.rb +48 -0
- data/app/models/spree/stock/coordinator.rb +14 -7
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock/inventory_unit_builder.rb +21 -0
- data/app/models/spree/stock/package.rb +38 -51
- data/app/models/spree/stock/packer.rb +13 -11
- data/app/models/spree/stock/prioritizer.rb +7 -7
- data/app/models/spree/stock/splitter/base.rb +2 -2
- data/app/models/spree/stock_item.rb +6 -9
- data/app/models/spree/stock_location.rb +17 -25
- data/app/models/spree/stock_movement.rb +1 -8
- data/app/models/spree/stock_transfer.rb +0 -2
- data/app/models/spree/store.rb +1 -1
- data/app/models/spree/tax_category.rb +2 -2
- data/app/models/spree/tax_rate.rb +16 -22
- data/app/models/spree/taxon.rb +1 -1
- data/app/models/spree/variant.rb +45 -23
- data/app/models/spree/zone.rb +17 -17
- data/app/models/spree/zone_member.rb +1 -1
- data/app/views/layouts/spree/base_mailer.html.erb +784 -0
- data/app/views/spree/order_mailer/cancel_email.html.erb +45 -0
- data/app/views/spree/order_mailer/cancel_email.text.erb +2 -2
- data/app/views/spree/order_mailer/confirm_email.html.erb +84 -0
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -2
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +22 -0
- data/app/views/spree/shared/_base_mailer_footer.html.erb +20 -0
- data/app/views/spree/shared/_base_mailer_header.html.erb +31 -0
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +34 -0
- data/app/views/spree/test_mailer/test_email.html.erb +40 -0
- data/app/views/spree/test_mailer/test_email.text.erb +2 -2
- data/config/initializers/friendly_id.rb +88 -0
- data/config/initializers/premailer_assets.rb +1 -0
- data/config/initializers/user_class_extensions.rb +9 -22
- data/config/locales/en.yml +180 -12
- data/db/default/spree/states.rb +73 -55
- data/db/migrate/20130213191427_create_default_stock.rb +1 -0
- data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -5
- data/db/migrate/20140309033438_create_store_from_preferences.rb +0 -7
- data/db/migrate/20140318191500_create_spree_taxons_promotion_rules.rb +8 -0
- data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +1 -1
- data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +5 -3
- data/db/migrate/20140625214618_create_spree_refunds.rb +12 -0
- data/db/migrate/20140702140656_create_spree_return_authorization_inventory_unit.rb +12 -0
- data/db/migrate/20140707125621_rename_return_authorization_inventory_unit_to_return_items.rb +5 -0
- data/db/migrate/20140709160534_backfill_line_item_pre_tax_amount.rb +10 -0
- data/db/migrate/20140710041921_recreate_spree_return_authorizations.rb +55 -0
- data/db/migrate/20140710181204_add_amount_fields_to_return_items.rb +7 -0
- data/db/migrate/20140710190048_drop_return_authorization_amount.rb +5 -0
- data/db/migrate/20140713140455_create_spree_return_authorization_reasons.rb +28 -0
- data/db/migrate/20140713140527_create_spree_refund_reasons.rb +14 -0
- data/db/migrate/20140713142214_rename_return_authorization_reason.rb +5 -0
- data/db/migrate/20140715182625_create_spree_promotion_categories.rb +11 -0
- data/db/migrate/20140716204111_drop_received_at_on_return_items.rb +9 -0
- data/db/migrate/20140716212330_add_reception_and_acceptance_status_to_return_items.rb +6 -0
- data/db/migrate/20140717155155_create_default_refund_reason.rb +9 -0
- data/db/migrate/20140717185932_add_default_to_spree_stock_locations.rb +5 -0
- data/db/migrate/20140718133010_create_spree_customer_returns.rb +9 -0
- data/db/migrate/20140718133349_add_customer_return_id_to_return_item.rb +6 -0
- data/db/migrate/20140718195325_create_friendly_id_slugs.rb +15 -0
- data/db/migrate/20140723004419_rename_spree_refund_return_authorization_id.rb +5 -0
- data/db/migrate/20140723152808_increase_return_item_pre_tax_amount_precision.rb +13 -0
- data/db/migrate/20140723214541_copy_product_slugs_to_slug_history.rb +15 -0
- data/db/migrate/20140725131539_create_spree_reimbursements.rb +21 -0
- data/db/migrate/20140728225422_add_promotionable_to_spree_products.rb +5 -0
- data/db/migrate/20140729133613_add_exchange_inventory_unit_foreign_keys.rb +7 -0
- data/db/migrate/20140730155938_add_acceptance_status_errors_to_return_item.rb +5 -0
- data/db/migrate/20140731150017_create_spree_reimbursement_types.rb +20 -0
- data/db/migrate/20140805171035_add_default_to_spree_credit_cards.rb +5 -0
- data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +10 -0
- data/db/migrate/20140806144901_add_type_to_reimbursement_type.rb +9 -0
- data/db/migrate/20140808184039_create_spree_reimbursement_credits.rb +10 -0
- data/db/migrate/20140827170513_add_meta_title_to_spree_products.rb +7 -0
- data/db/migrate/20140924164824_add_code_to_spree_tax_categories.rb +5 -0
- data/db/migrate/20141002191113_add_code_to_spree_shipping_methods.rb +5 -0
- data/db/migrate/20141007230328_add_cancel_audit_fields_to_spree_orders.rb +6 -0
- data/db/migrate/20141009204607_add_store_id_to_orders.rb +8 -0
- data/lib/generators/spree/install/install_generator.rb +7 -3
- data/lib/spree/core.rb +11 -10
- data/lib/spree/core/controller_helpers/common.rb +3 -10
- data/lib/spree/core/controller_helpers/order.rb +15 -12
- data/lib/spree/core/controller_helpers/strong_parameters.rb +9 -9
- data/lib/spree/core/engine.rb +8 -1
- data/lib/spree/core/importer/order.rb +5 -17
- data/lib/spree/core/search/base.rb +1 -1
- data/lib/spree/core/validators/email.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/instrumentation.rb +41 -0
- data/lib/spree/migrations.rb +3 -7
- data/lib/spree/money.rb +2 -2
- data/lib/spree/permitted_attributes.rb +10 -9
- data/lib/spree/testing_support/ability_helpers.rb +25 -25
- data/lib/spree/testing_support/authorization_helpers.rb +3 -5
- data/lib/spree/testing_support/capybara_ext.rb +2 -2
- data/lib/spree/testing_support/factories/calculator_factory.rb +0 -8
- data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
- data/lib/spree/testing_support/factories/customer_return_factory.rb +31 -0
- data/lib/spree/testing_support/factories/inventory_unit_factory.rb +1 -0
- data/lib/spree/testing_support/factories/line_item_factory.rb +2 -1
- data/lib/spree/testing_support/factories/order_factory.rb +11 -6
- data/lib/spree/testing_support/factories/promotion_category_factory.rb +6 -0
- data/lib/spree/testing_support/factories/promotion_factory.rb +9 -7
- data/lib/spree/testing_support/factories/refund_factory.rb +14 -0
- data/lib/spree/testing_support/factories/reimbursement_factory.rb +16 -0
- data/lib/spree/testing_support/factories/reimbursement_type_factory.rb +7 -0
- data/lib/spree/testing_support/factories/return_authorization_factory.rb +9 -3
- data/lib/spree/testing_support/factories/return_item_factory.rb +10 -0
- data/lib/spree/testing_support/factories/shipment_factory.rb +1 -0
- data/lib/spree/testing_support/factories/shipping_method_factory.rb +3 -2
- data/lib/spree/testing_support/factories/stock_factory.rb +12 -11
- data/lib/spree/testing_support/flash.rb +2 -2
- data/lib/tasks/email.rake +7 -0
- data/lib/tasks/exchanges.rake +70 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
- metadata +163 -47
- data/app/models/concerns/spree/ransackable_attributes.rb +0 -19
- data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +0 -5
- data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +0 -13
- data/db/migrate/20141105213646_update_classifications_positions.rb +0 -9
- data/db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb +0 -5
- data/db/migrate/20150515211137_fix_adjustment_order_id.rb +0 -70
- data/lib/spree/core/adjustment_source.rb +0 -26
- data/lib/spree/core/calculated_adjustments.rb +0 -35
- data/lib/spree/core/controller_helpers.rb +0 -20
- data/lib/spree/core/user_address.rb +0 -32
- data/lib/spree/core/user_payment_source.rb +0 -20
- data/lib/spree/localized_number.rb +0 -20
@@ -58,7 +58,7 @@ module Spree
|
|
58
58
|
end
|
59
59
|
|
60
60
|
event :return do
|
61
|
-
transition to: :returned, from: :awaiting_return,
|
61
|
+
transition to: :returned, from: [:complete, :awaiting_return, :canceled], if: :all_inventory_units_returned?
|
62
62
|
end
|
63
63
|
|
64
64
|
event :resume do
|
@@ -78,6 +78,10 @@ module Spree
|
|
78
78
|
order.process_payments!
|
79
79
|
end
|
80
80
|
end
|
81
|
+
after_transition to: :complete, do: :persist_user_credit_card
|
82
|
+
before_transition to: :payment, do: :set_shipments_cost
|
83
|
+
before_transition to: :payment, do: :create_tax_charge!
|
84
|
+
before_transition to: :payment, do: :assign_default_credit_card
|
81
85
|
end
|
82
86
|
|
83
87
|
before_transition from: :cart, do: :ensure_line_items_present
|
@@ -88,11 +92,6 @@ module Spree
|
|
88
92
|
before_transition from: :address, do: :persist_user_address!
|
89
93
|
end
|
90
94
|
|
91
|
-
if states[:payment]
|
92
|
-
before_transition to: :payment, do: :set_shipments_cost
|
93
|
-
before_transition to: :payment, do: :create_tax_charge!
|
94
|
-
end
|
95
|
-
|
96
95
|
if states[:delivery]
|
97
96
|
before_transition to: :delivery, do: :create_proposed_shipments
|
98
97
|
before_transition to: :delivery, do: :ensure_available_shipping_rates
|
@@ -102,8 +101,6 @@ module Spree
|
|
102
101
|
|
103
102
|
before_transition to: :resumed, do: :ensure_line_items_are_in_stock
|
104
103
|
|
105
|
-
before_transition to: :complete, do: :ensure_line_items_are_in_stock
|
106
|
-
|
107
104
|
after_transition to: :complete, do: :finalize!
|
108
105
|
after_transition to: :resumed, do: :after_resume
|
109
106
|
after_transition to: :canceled, do: :after_cancel
|
@@ -203,8 +200,12 @@ module Spree
|
|
203
200
|
step.present? && self.checkout_steps.include?(step)
|
204
201
|
end
|
205
202
|
|
203
|
+
def passed_checkout_step?(step)
|
204
|
+
has_checkout_step?(step) && checkout_step_index(step) < checkout_step_index(self.state)
|
205
|
+
end
|
206
|
+
|
206
207
|
def checkout_step_index(step)
|
207
|
-
self.checkout_steps.index(step)
|
208
|
+
self.checkout_steps.index(step).to_i
|
208
209
|
end
|
209
210
|
|
210
211
|
def self.removed_transitions
|
@@ -228,10 +229,7 @@ module Spree
|
|
228
229
|
|
229
230
|
# Set existing card after setting permitted parameters because
|
230
231
|
# rails would slice parameters containg ruby objects, apparently
|
231
|
-
|
232
|
-
# Need to check both outside and inside :order beacuse frontend
|
233
|
-
# sends existing_card out of :order
|
234
|
-
existing_card_id = @updating_params[:existing_card] || (@updating_params[:order] ? @updating_params[:order][:existing_card] : nil)
|
232
|
+
existing_card_id = @updating_params[:order] ? @updating_params[:order][:existing_card] : nil
|
235
233
|
|
236
234
|
if existing_card_id.present?
|
237
235
|
credit_card = CreditCard.find existing_card_id
|
@@ -273,6 +271,22 @@ module Spree
|
|
273
271
|
end
|
274
272
|
end
|
275
273
|
|
274
|
+
def persist_user_credit_card
|
275
|
+
if !self.temporary_credit_card && self.user_id && self.valid_credit_cards.present?
|
276
|
+
default_cc = self.valid_credit_cards.first
|
277
|
+
default_cc.user_id = self.user_id
|
278
|
+
default_cc.default = true
|
279
|
+
default_cc.save
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def assign_default_credit_card
|
284
|
+
if self.payments.from_credit_card.count == 0 && self.user && self.user.default_credit_card.try(:valid?)
|
285
|
+
cc = self.user.default_credit_card
|
286
|
+
self.payments.create!(payment_method_id: cc.payment_method_id, source: cc)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
276
290
|
private
|
277
291
|
# For payment step, filter order parameters to produce the expected nested
|
278
292
|
# attributes for a single payment and its source, discarding attributes
|
@@ -288,19 +302,17 @@ module Spree
|
|
288
302
|
# }
|
289
303
|
#
|
290
304
|
def update_params_payment_source
|
291
|
-
if
|
292
|
-
|
293
|
-
source_params = @updating_params.delete(:payment_source)[@updating_params[:order][:payments_attributes].first[:payment_method_id].to_s]
|
305
|
+
if @updating_params[:payment_source].present?
|
306
|
+
source_params = @updating_params.delete(:payment_source)[@updating_params[:order][:payments_attributes].first[:payment_method_id].to_s]
|
294
307
|
|
295
|
-
|
296
|
-
|
297
|
-
end
|
308
|
+
if source_params
|
309
|
+
@updating_params[:order][:payments_attributes].first[:source_attributes] = source_params
|
298
310
|
end
|
311
|
+
end
|
299
312
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
end
|
313
|
+
if @updating_params[:order] && (@updating_params[:order][:payments_attributes] || @updating_params[:order][:existing_card])
|
314
|
+
@updating_params[:order][:payments_attributes] ||= [{}]
|
315
|
+
@updating_params[:order][:payments_attributes].first[:amount] = self.total
|
304
316
|
end
|
305
317
|
end
|
306
318
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Spree
|
2
|
+
class Order < Spree::Base
|
3
|
+
module Payments
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
# processes any pending payments and must return a boolean as it's
|
7
|
+
# return value is used by the checkout state_machine to determine
|
8
|
+
# success or failure of the 'complete' event for the order
|
9
|
+
#
|
10
|
+
# Returns:
|
11
|
+
#
|
12
|
+
# - true if all pending_payments processed successfully
|
13
|
+
#
|
14
|
+
# - true if a payment failed, ie. raised a GatewayError
|
15
|
+
# which gets rescued and converted to TRUE when
|
16
|
+
# :allow_checkout_gateway_error is set to true
|
17
|
+
#
|
18
|
+
# - false if a payment failed, ie. raised a GatewayError
|
19
|
+
# which gets rescued and converted to FALSE when
|
20
|
+
# :allow_checkout_on_gateway_error is set to false
|
21
|
+
#
|
22
|
+
def process_payments!
|
23
|
+
process_payments_with(:process!)
|
24
|
+
end
|
25
|
+
|
26
|
+
def authorize_payments!
|
27
|
+
process_payments_with(:authorize!)
|
28
|
+
end
|
29
|
+
|
30
|
+
def capture_payments!
|
31
|
+
process_payments_with(:purchase!)
|
32
|
+
end
|
33
|
+
|
34
|
+
def pending_payments
|
35
|
+
payments.select { |payment| payment.pending? }
|
36
|
+
end
|
37
|
+
|
38
|
+
def unprocessed_payments
|
39
|
+
payments.select { |payment| payment.checkout? }
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def process_payments_with(method)
|
45
|
+
# Don't run if there is nothing to pay.
|
46
|
+
return if payment_total >= total
|
47
|
+
# Prevent orders from transitioning to complete without a successfully processed payment.
|
48
|
+
raise Core::GatewayError.new(Spree.t(:no_payment_found)) if unprocessed_payments.empty?
|
49
|
+
|
50
|
+
unprocessed_payments.each do |payment|
|
51
|
+
break if payment_total >= total
|
52
|
+
|
53
|
+
payment.public_send(method)
|
54
|
+
|
55
|
+
if payment.completed?
|
56
|
+
self.payment_total += payment.amount
|
57
|
+
end
|
58
|
+
end
|
59
|
+
rescue Core::GatewayError => e
|
60
|
+
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
61
|
+
errors.add(:base, e.message) and return result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -6,9 +6,10 @@ module Spree
|
|
6
6
|
@order = order
|
7
7
|
end
|
8
8
|
|
9
|
-
def add(variant, quantity = 1,
|
10
|
-
line_item = add_to_line_item(variant, quantity,
|
9
|
+
def add(variant, quantity = 1, options = {})
|
10
|
+
line_item = add_to_line_item(variant, quantity, options)
|
11
11
|
reload_totals
|
12
|
+
shipment = options[:shipment]
|
12
13
|
shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
|
13
14
|
PromotionHandler::Cart.new(order, line_item).activate
|
14
15
|
ItemAdjustments.new(line_item).update
|
@@ -16,9 +17,10 @@ module Spree
|
|
16
17
|
line_item
|
17
18
|
end
|
18
19
|
|
19
|
-
def remove(variant, quantity = 1,
|
20
|
-
line_item = remove_from_line_item(variant, quantity,
|
20
|
+
def remove(variant, quantity = 1, options = {})
|
21
|
+
line_item = remove_from_line_item(variant, quantity, options)
|
21
22
|
reload_totals
|
23
|
+
shipment = options[:shipment]
|
22
24
|
shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
|
23
25
|
PromotionHandler::Cart.new(order, line_item).activate
|
24
26
|
ItemAdjustments.new(line_item).update
|
@@ -27,8 +29,8 @@ module Spree
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def update_cart(params)
|
30
|
-
if order.update_attributes(params)
|
31
|
-
order.line_items = order.line_items.select {|li| li.quantity > 0 }
|
32
|
+
if order.update_attributes(filter_order_items(params))
|
33
|
+
order.line_items = order.line_items.select { |li| li.quantity > 0 }
|
32
34
|
# Update totals, then check if the order is eligible for any cart promotions.
|
33
35
|
# If we do not update first, then the item total will be wrong and ItemTotal
|
34
36
|
# promotion rules would not be triggered.
|
@@ -43,6 +45,18 @@ module Spree
|
|
43
45
|
end
|
44
46
|
|
45
47
|
private
|
48
|
+
|
49
|
+
def filter_order_items(params)
|
50
|
+
filtered_params = params.symbolize_keys
|
51
|
+
return filtered_params if filtered_params[:line_items_attributes].nil? || filtered_params[:line_items_attributes][:id]
|
52
|
+
|
53
|
+
params[:line_items_attributes].each_pair do |id, value|
|
54
|
+
line_item_id = value[:id]
|
55
|
+
filtered_params[:line_items_attributes].delete(id) unless Spree::LineItem.find_by_id(line_item_id.to_i)
|
56
|
+
end
|
57
|
+
filtered_params
|
58
|
+
end
|
59
|
+
|
46
60
|
def order_updater
|
47
61
|
@updater ||= OrderUpdater.new(order)
|
48
62
|
end
|
@@ -53,32 +67,28 @@ module Spree
|
|
53
67
|
order.reload
|
54
68
|
end
|
55
69
|
|
56
|
-
def add_to_line_item(variant, quantity,
|
57
|
-
line_item = grab_line_item_by_variant(variant)
|
70
|
+
def add_to_line_item(variant, quantity, options = {})
|
71
|
+
line_item = grab_line_item_by_variant(variant, false, options)
|
58
72
|
|
59
73
|
if line_item
|
60
|
-
line_item.target_shipment = shipment
|
61
74
|
line_item.quantity += quantity.to_i
|
62
75
|
line_item.currency = currency unless currency.nil?
|
63
76
|
else
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
else
|
70
|
-
line_item.price = variant.price
|
71
|
-
end
|
77
|
+
opts = { currency: order.currency }.merge ActionController::Parameters.new(options).
|
78
|
+
permit(PermittedAttributes.line_item_attributes)
|
79
|
+
line_item = order.line_items.new(quantity: quantity,
|
80
|
+
variant: variant,
|
81
|
+
options: opts)
|
72
82
|
end
|
73
|
-
|
74
|
-
line_item.save
|
83
|
+
line_item.target_shipment = options[:shipment] if options.has_key? :shipment
|
84
|
+
line_item.save!
|
75
85
|
line_item
|
76
86
|
end
|
77
87
|
|
78
|
-
def remove_from_line_item(variant, quantity,
|
79
|
-
line_item = grab_line_item_by_variant(variant, true)
|
88
|
+
def remove_from_line_item(variant, quantity, options = {})
|
89
|
+
line_item = grab_line_item_by_variant(variant, true, options)
|
80
90
|
line_item.quantity -= quantity
|
81
|
-
line_item.target_shipment= shipment
|
91
|
+
line_item.target_shipment= options[:shipment]
|
82
92
|
|
83
93
|
if line_item.quantity == 0
|
84
94
|
line_item.destroy
|
@@ -89,8 +99,8 @@ module Spree
|
|
89
99
|
line_item
|
90
100
|
end
|
91
101
|
|
92
|
-
def grab_line_item_by_variant(variant, raise_error = false)
|
93
|
-
line_item = order.find_line_item_by_variant(variant)
|
102
|
+
def grab_line_item_by_variant(variant, raise_error = false, options = {})
|
103
|
+
line_item = order.find_line_item_by_variant(variant, options)
|
94
104
|
|
95
105
|
if !line_item.present? && raise_error
|
96
106
|
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
|
@@ -9,8 +9,10 @@ module Spree
|
|
9
9
|
@errors = ActiveModel::Errors.new(self)
|
10
10
|
end
|
11
11
|
|
12
|
-
def populate(variant_id, quantity)
|
13
|
-
|
12
|
+
def populate(variant_id, quantity, options = {})
|
13
|
+
# protect against passing a nil hash being passed in
|
14
|
+
# due to an empty params[:options]
|
15
|
+
attempt_cart_add(variant_id, quantity, options || {})
|
14
16
|
valid?
|
15
17
|
end
|
16
18
|
|
@@ -20,7 +22,7 @@ module Spree
|
|
20
22
|
|
21
23
|
private
|
22
24
|
|
23
|
-
def attempt_cart_add(variant_id, quantity)
|
25
|
+
def attempt_cart_add(variant_id, quantity, options = {})
|
24
26
|
quantity = quantity.to_i
|
25
27
|
# 2,147,483,647 is crazy.
|
26
28
|
# See issue #2695.
|
@@ -31,7 +33,7 @@ module Spree
|
|
31
33
|
|
32
34
|
variant = Spree::Variant.find(variant_id)
|
33
35
|
if quantity > 0
|
34
|
-
line_item = @order.contents.add(variant, quantity, currency)
|
36
|
+
line_item = @order.contents.add(variant, quantity, options.merge(currency: currency))
|
35
37
|
unless line_item.valid?
|
36
38
|
errors.add(:base, line_item.errors.messages.values.join(" "))
|
37
39
|
return false
|
@@ -24,6 +24,7 @@ module Spree
|
|
24
24
|
run_hooks
|
25
25
|
persist_totals
|
26
26
|
end
|
27
|
+
Spree.instrument_method self, :update
|
27
28
|
|
28
29
|
def run_hooks
|
29
30
|
update_hooks.each { |hook| order.send hook }
|
@@ -111,6 +112,7 @@ module Spree
|
|
111
112
|
updated_at: Time.now,
|
112
113
|
)
|
113
114
|
end
|
115
|
+
Spree.instrument_method self, :persist_totals
|
114
116
|
|
115
117
|
# Updates the +shipment_state+ attribute according to the following logic:
|
116
118
|
#
|
@@ -158,7 +160,9 @@ module Spree
|
|
158
160
|
last_state = order.payment_state
|
159
161
|
if payments.present? && payments.valid.size == 0
|
160
162
|
order.payment_state = 'failed'
|
161
|
-
elsif order.state == 'canceled'
|
163
|
+
elsif !payments.present? && order.state == 'canceled'
|
164
|
+
order.payment_state = 'void'
|
165
|
+
elsif order.state == 'canceled' && order.payment_total == 0 && payments.completed.size > 0
|
162
166
|
order.payment_state = 'void'
|
163
167
|
else
|
164
168
|
order.payment_state = 'balance_due' if order.outstanding_balance > 0
|
@@ -168,5 +172,10 @@ module Spree
|
|
168
172
|
order.state_changed('payment') if last_state != order.payment_state
|
169
173
|
order.payment_state
|
170
174
|
end
|
175
|
+
|
176
|
+
private
|
177
|
+
def round_money(n)
|
178
|
+
(n * 100).round / 100.0
|
179
|
+
end
|
171
180
|
end
|
172
181
|
end
|
data/app/models/spree/payment.rb
CHANGED
@@ -8,15 +8,14 @@ module Spree
|
|
8
8
|
|
9
9
|
belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :payments
|
10
10
|
belongs_to :source, polymorphic: true
|
11
|
-
belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
|
11
|
+
belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
|
12
12
|
|
13
|
-
has_many :offsets, -> {
|
14
|
-
class_name: "Spree::Payment", foreign_key: :source_id
|
13
|
+
has_many :offsets, -> { offset_payment }, class_name: "Spree::Payment", foreign_key: :source_id
|
15
14
|
has_many :log_entries, as: :source
|
16
15
|
has_many :state_changes, as: :stateful
|
17
16
|
has_many :capture_events, :class_name => 'Spree::PaymentCaptureEvent'
|
17
|
+
has_many :refunds, inverse_of: :payment
|
18
18
|
|
19
|
-
validates_presence_of :payment_method
|
20
19
|
before_validation :validate_source
|
21
20
|
before_create :set_unique_identifier
|
22
21
|
|
@@ -39,13 +38,23 @@ module Spree
|
|
39
38
|
|
40
39
|
scope :from_credit_card, -> { where(source_type: 'Spree::CreditCard') }
|
41
40
|
scope :with_state, ->(s) { where(state: s.to_s) }
|
41
|
+
# "offset" is reserved by activerecord
|
42
|
+
scope :offset_payment, -> { where("source_type = 'Spree::Payment' AND amount < 0 AND state = 'completed'") }
|
43
|
+
|
44
|
+
scope :checkout, -> { with_state('checkout') }
|
42
45
|
scope :completed, -> { with_state('completed') }
|
43
46
|
scope :pending, -> { with_state('pending') }
|
44
47
|
scope :processing, -> { with_state('processing') }
|
45
48
|
scope :failed, -> { with_state('failed') }
|
49
|
+
|
46
50
|
scope :risky, -> { where("avs_response IN (?) OR (cvv_response_code IS NOT NULL and cvv_response_code != 'M') OR state = 'failed'", RISKY_AVS_CODES) }
|
47
51
|
scope :valid, -> { where.not(state: %w(failed invalid)) }
|
48
52
|
|
53
|
+
# transaction_id is much easier to understand
|
54
|
+
def transaction_id
|
55
|
+
response_code
|
56
|
+
end
|
57
|
+
|
49
58
|
def persist_invalid
|
50
59
|
return unless ['failed', 'invalid'].include?(state)
|
51
60
|
state_will_change!
|
@@ -115,7 +124,7 @@ module Spree
|
|
115
124
|
end
|
116
125
|
|
117
126
|
def credit_allowed
|
118
|
-
amount - offsets_total.abs
|
127
|
+
amount - (offsets_total.abs + refunds.sum(:amount))
|
119
128
|
end
|
120
129
|
|
121
130
|
def can_credit?
|
@@ -158,10 +167,6 @@ module Spree
|
|
158
167
|
amount - capture_events.sum(:amount)
|
159
168
|
end
|
160
169
|
|
161
|
-
def editable?
|
162
|
-
checkout? || pending?
|
163
|
-
end
|
164
|
-
|
165
170
|
private
|
166
171
|
|
167
172
|
def validate_source
|
@@ -179,8 +184,8 @@ module Spree
|
|
179
184
|
end
|
180
185
|
|
181
186
|
def create_payment_profile
|
182
|
-
|
183
|
-
return
|
187
|
+
# Payment profile cannot be created without source
|
188
|
+
return unless source
|
184
189
|
# Imported payments shouldn't create a payment profile.
|
185
190
|
return if source.imported
|
186
191
|
|
@@ -190,15 +195,13 @@ module Spree
|
|
190
195
|
end
|
191
196
|
|
192
197
|
def invalidate_old_payments
|
193
|
-
|
194
|
-
|
195
|
-
payment.invalidate!
|
196
|
-
end
|
198
|
+
order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
|
199
|
+
payment.invalidate!
|
197
200
|
end
|
198
201
|
end
|
199
202
|
|
200
203
|
def update_order
|
201
|
-
if completed?
|
204
|
+
if self.completed?
|
202
205
|
order.updater.update_payment_total
|
203
206
|
end
|
204
207
|
|