spree_core 2.1.12 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/helpers/spree/base_helper.rb +4 -7
- data/app/helpers/spree/products_helper.rb +11 -9
- data/app/helpers/spree/store_helper.rb +5 -0
- data/app/models/spree/ability.rb +4 -0
- data/app/models/spree/address.rb +6 -6
- data/app/models/spree/adjustment.rb +40 -61
- data/app/models/spree/app_configuration.rb +1 -14
- data/app/models/spree/calculator.rb +12 -4
- data/app/models/spree/calculator/default_tax.rb +42 -38
- data/app/models/spree/calculator/flat_percent_item_total.rb +2 -4
- data/app/models/spree/calculator/free_shipping.rb +5 -2
- data/app/models/spree/calculator/percent_on_line_item.rb +15 -0
- data/app/models/spree/calculator/percent_per_item.rb +3 -0
- data/app/models/spree/classification.rb +3 -2
- data/app/models/spree/credit_card.rb +7 -25
- data/app/models/spree/gateway/bogus.rb +5 -5
- data/app/models/spree/gateway/bogus_simple.rb +0 -8
- data/app/models/spree/image.rb +0 -9
- data/app/models/spree/inventory_unit.rb +10 -4
- data/app/models/spree/item_adjustments.rb +65 -0
- data/app/models/spree/legacy_user.rb +1 -0
- data/app/models/spree/line_item.rb +33 -13
- data/app/models/spree/option_type.rb +2 -2
- data/app/models/spree/option_value.rb +1 -1
- data/app/models/spree/order.rb +109 -89
- data/app/models/spree/order/checkout.rb +48 -0
- data/app/models/spree/order_contents.rb +72 -37
- data/app/models/spree/order_inventory.rb +65 -68
- data/app/models/spree/order_populator.rb +3 -17
- data/app/models/spree/order_updater.rb +63 -44
- data/app/models/spree/payment.rb +20 -5
- data/app/models/spree/payment/processing.rb +19 -25
- data/app/models/spree/payment_capture_event.rb +9 -0
- data/app/models/spree/payment_method/check.rb +0 -2
- data/app/models/spree/price.rb +1 -1
- data/app/models/spree/product.rb +14 -16
- data/app/models/spree/product/scopes.rb +4 -6
- data/app/models/spree/product_option_type.rb +2 -2
- data/app/models/spree/product_property.rb +2 -2
- data/app/models/spree/promotion.rb +71 -50
- data/app/models/spree/promotion/actions/create_adjustment.rb +31 -32
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +83 -0
- data/app/models/spree/promotion/actions/free_shipping.rb +36 -0
- data/app/models/spree/promotion/rules/first_order.rb +4 -0
- data/app/models/spree/promotion/rules/item_total.rb +5 -1
- data/app/models/spree/promotion/rules/product.rb +4 -0
- data/app/models/spree/promotion/rules/user.rb +5 -6
- data/app/models/spree/promotion/rules/user_logged_in.rb +4 -0
- data/app/models/spree/promotion_action.rb +1 -5
- data/app/models/spree/promotion_handler/cart.rb +38 -0
- data/app/models/spree/promotion_handler/coupon.rb +76 -0
- data/app/models/spree/promotion_handler/free_shipping.rb +31 -0
- data/app/models/spree/promotion_handler/page.rb +24 -0
- data/app/models/spree/promotion_rule.rb +15 -7
- data/app/models/spree/property.rb +1 -1
- data/app/models/spree/return_authorization.rb +7 -1
- data/app/models/spree/shipment.rb +113 -49
- data/app/models/spree/shipping_calculator.rb +4 -5
- data/app/models/spree/shipping_category.rb +2 -2
- data/app/models/spree/shipping_method.rb +12 -6
- data/app/models/spree/shipping_rate.rb +27 -7
- data/app/models/spree/stock/availability_validator.rb +1 -1
- data/app/models/spree/stock/estimator.rb +13 -1
- data/app/models/spree/stock/package.rb +11 -7
- data/app/models/spree/stock/packer.rb +3 -3
- data/app/models/spree/stock/quantifier.rb +9 -1
- data/app/models/spree/stock_item.rb +11 -6
- data/app/models/spree/stock_movement.rb +1 -2
- data/app/models/spree/tax_category.rb +6 -1
- data/app/models/spree/tax_rate.rb +57 -49
- data/app/models/spree/taxon.rb +10 -5
- data/app/models/spree/taxonomy.rb +5 -2
- data/app/models/spree/variant.rb +33 -16
- data/app/models/spree/zone.rb +24 -24
- data/app/views/spree/shared/_routes.html.erb +3 -0
- data/config/locales/en.yml +42 -26
- data/db/migrate/20130213191427_create_default_stock.rb +3 -3
- data/db/migrate/20130413230529_add_name_to_spree_credit_cards.rb +5 -0
- data/db/migrate/20130414000512_update_name_fields_on_spree_credit_cards.rb +13 -0
- data/db/migrate/20130417120035_update_adjustment_states.rb +2 -2
- data/db/migrate/20130417123427_add_shipping_rates_to_shipments.rb +1 -1
- data/db/migrate/20130509115210_add_number_to_stock_transfer.rb +1 -1
- data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +0 -5
- data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +7 -5
- data/db/migrate/20130807024301_upgrade_adjustments.rb +39 -0
- data/db/migrate/20130807024302_rename_adjustment_fields.rb +17 -0
- data/db/migrate/20130813004002_add_shipment_total_to_spree_orders.rb +5 -0
- data/db/migrate/20130813232134_rename_activators_to_promotions.rb +5 -0
- data/db/migrate/20130815000406_add_adjustment_total_to_line_items.rb +5 -0
- data/db/migrate/20130815024413_add_adjustment_total_to_shipments.rb +5 -0
- data/db/migrate/20130828234942_add_tax_total_to_line_items_shipments_and_orders.rb +8 -0
- data/db/migrate/20130830001159_migrate_old_shipping_calculators.rb +1 -1
- data/db/migrate/20130903183026_add_code_to_spree_promotion_rules.rb +5 -0
- data/db/migrate/20130917024658_remove_promotions_event_name_field.rb +5 -0
- data/db/migrate/20130924040529_add_promo_total_to_line_items_and_shipments_and_orders.rb +7 -0
- data/db/migrate/20131001013410_remove_unused_credit_card_fields.rb +7 -3
- data/db/migrate/20131107132123_add_tax_category_to_variants.rb +6 -0
- data/db/migrate/20131118043959_add_included_to_adjustments.rb +5 -0
- data/db/migrate/20131118050234_rename_tax_total_fields.rb +11 -0
- data/db/migrate/20131118183431_add_line_item_id_to_spree_inventory_units.rb +21 -0
- data/db/migrate/20131127001002_add_position_to_classifications.rb +5 -0
- data/db/migrate/20131211112807_create_spree_orders_promotions.rb +8 -0
- data/db/migrate/20131218054603_add_item_count_to_spree_orders.rb +5 -0
- data/db/migrate/20140106224208_rename_permalink_to_slug_for_products.rb +5 -0
- data/db/migrate/20140124023232_rename_activator_id_in_rules_and_actions_to_promotion_id.rb +6 -0
- data/db/migrate/20140203161722_add_approver_id_and_approved_at_to_orders.rb +6 -0
- data/db/migrate/20140204115338_add_confirmation_delivered_to_spree_orders.rb +5 -0
- data/db/migrate/20140205120320_create_spree_payment_capture_events.rb +12 -0
- data/db/migrate/20140205144710_add_uncaptured_amount_to_payments.rb +5 -0
- data/db/migrate/20140207085910_add_tax_category_id_to_shipping_methods.rb +5 -0
- data/db/migrate/20140207093021_add_tax_rate_id_to_shipping_rates.rb +5 -0
- data/db/migrate/20140211040159_add_pre_tax_amount_to_line_items_and_shipments.rb +6 -0
- data/db/migrate/20140213184916_add_more_indexes.rb +13 -0
- data/db/migrate/20140219060952_add_considered_risky_to_orders.rb +5 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +1 -6
- data/lib/generators/spree/install/install_generator.rb +6 -6
- data/lib/generators/spree/install/templates/{app/assets/javascripts/admin → vendor/assets/javascripts/spree/backend}/all.js +3 -3
- data/lib/generators/spree/install/templates/{app/assets/javascripts/store → vendor/assets/javascripts/spree/frontend}/all.js +3 -3
- data/lib/generators/spree/install/templates/{app/assets/stylesheets/store → vendor/assets/stylesheets/spree/backend}/all.css +3 -3
- data/lib/generators/spree/install/templates/{app/assets/stylesheets/admin → vendor/assets/stylesheets/spree/frontend}/all.css +3 -3
- data/lib/spree/core.rb +21 -8
- data/lib/spree/core/calculated_adjustments.rb +0 -40
- data/lib/spree/core/controller_helpers.rb +5 -0
- data/lib/spree/core/controller_helpers/auth.rb +2 -2
- data/lib/spree/core/controller_helpers/common.rb +0 -5
- data/lib/spree/core/controller_helpers/order.rb +8 -9
- data/lib/spree/core/engine.rb +10 -17
- data/lib/spree/core/permalinks.rb +1 -1
- data/lib/spree/core/product_duplicator.rb +3 -8
- data/lib/spree/core/user_address.rb +1 -1
- data/lib/spree/core/validators/email.rb +23 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/money.rb +1 -1
- data/lib/spree/permitted_attributes.rb +2 -2
- data/lib/spree/testing_support/caching.rb +47 -0
- data/lib/spree/testing_support/factories/adjustment_factory.rb +11 -2
- data/lib/spree/testing_support/factories/credit_card_factory.rb +2 -1
- data/lib/spree/testing_support/factories/order_factory.rb +10 -5
- data/lib/spree/testing_support/factories/payment_factory.rb +2 -2
- data/lib/spree/testing_support/factories/payment_method_factory.rb +3 -3
- data/lib/spree/testing_support/factories/promotion_factory.rb +16 -1
- data/lib/spree/testing_support/factories/shipment_factory.rb +8 -4
- data/lib/spree/testing_support/factories/shipping_method_factory.rb +1 -3
- data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
- data/lib/spree/testing_support/factories/tax_rate_factory.rb +2 -2
- data/lib/spree/testing_support/order_walkthrough.rb +1 -1
- data/lib/tasks/core.rake +2 -2
- data/vendor/assets/fonts/FontAwesome.otf +0 -0
- data/vendor/assets/fonts/fontawesome-webfont.eot +0 -0
- data/vendor/assets/fonts/fontawesome-webfont.svg +399 -0
- data/vendor/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/vendor/assets/fonts/fontawesome-webfont.woff +0 -0
- data/vendor/assets/stylesheets/font-awesome.scss +1475 -0
- metadata +73 -44
- data/app/assets/javascripts/admin/handlebar_extensions.js +0 -9
- data/app/helpers/spree/admin/adjustments_helper.rb +0 -26
- data/app/helpers/spree/admin/images_helper.rb +0 -18
- data/app/helpers/spree/promotion_rules_helper.rb +0 -13
- data/app/models/spree/activator.rb +0 -29
- data/app/models/spree/calculator/per_item.rb +0 -41
- data/app/models/spree/stock/remaining_packer.rb +0 -22
- data/app/views/spree/payments/_payment.html.erb +0 -18
- data/db/migrate/20131118041203_add_tax_total_to_spree_orders.rb +0 -5
- data/db/migrate/20131118043021_add_order_id_to_spree_adjustments.rb +0 -6
- data/db/migrate/20131118074808_add_included_to_spree_adjustments.rb +0 -5
- data/db/migrate/20140415041315_add_user_id_created_by_id_index_to_order.rb +0 -5
- data/lib/spree/core/gateway_error.rb +0 -5
- data/lib/spree/core/preference_rescue.rb +0 -25
- data/lib/spree/core/s3_support.rb +0 -25
- data/lib/spree/promo/coupon_applicator.rb +0 -71
- data/lib/spree/testing_support/factories/activator_factory.rb +0 -8
@@ -84,11 +84,22 @@ module Spree
|
|
84
84
|
if states[:delivery]
|
85
85
|
before_transition :to => :delivery, :do => :create_proposed_shipments
|
86
86
|
before_transition :to => :delivery, :do => :ensure_available_shipping_rates
|
87
|
+
before_transition :from => :delivery, :do => :apply_free_shipping_promotions
|
88
|
+
end
|
89
|
+
|
90
|
+
if states[:payment]
|
91
|
+
before_transition :to => :payment, :do => :set_shipments_cost
|
92
|
+
before_transition :to => :payment, :do => :create_tax_charge!
|
87
93
|
end
|
88
94
|
|
89
95
|
after_transition :to => :complete, :do => :finalize!
|
90
96
|
after_transition :to => :resumed, :do => :after_resume
|
91
97
|
after_transition :to => :canceled, :do => :after_cancel
|
98
|
+
|
99
|
+
after_transition :from => any - :cart, :to => any - [:confirm, :complete] do |order|
|
100
|
+
order.update_totals
|
101
|
+
order.persist_totals
|
102
|
+
end
|
92
103
|
end
|
93
104
|
end
|
94
105
|
|
@@ -190,6 +201,43 @@ module Spree
|
|
190
201
|
return false unless has_checkout_step?(self.state) && has_checkout_step?(state)
|
191
202
|
checkout_step_index(state) > checkout_step_index(self.state)
|
192
203
|
end
|
204
|
+
|
205
|
+
define_callbacks :updating_from_params, terminator: 'result == false'
|
206
|
+
|
207
|
+
set_callback :updating_from_params, :before, :update_params_payment_source
|
208
|
+
|
209
|
+
def update_from_params(params, permitted_params)
|
210
|
+
success = false
|
211
|
+
@updating_params = params
|
212
|
+
run_callbacks :updating_from_params do
|
213
|
+
attributes = @updating_params[:order] ? @updating_params[:order].permit(permitted_params) : {}
|
214
|
+
success = self.update_attributes(attributes)
|
215
|
+
end
|
216
|
+
@updating_params = nil
|
217
|
+
success
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
# For payment step, filter order parameters to produce the expected nested
|
222
|
+
# attributes for a single payment and its source, discarding attributes
|
223
|
+
# for payment methods other than the one selected
|
224
|
+
def update_params_payment_source
|
225
|
+
# respond_to check is necessary due to issue described in #2910
|
226
|
+
if has_checkout_step?("payment") && self.payment?
|
227
|
+
if @updating_params[:payment_source].present?
|
228
|
+
source_params = @updating_params.delete(:payment_source)[@updating_params[:order][:payments_attributes].first[:payment_method_id].underscore]
|
229
|
+
|
230
|
+
if source_params
|
231
|
+
@updating_params[:order][:payments_attributes].first[:source_attributes] = source_params
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
if (@updating_params[:order][:payments_attributes])
|
236
|
+
@updating_params[:order][:payments_attributes].first[:amount] = self.total
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
193
241
|
end
|
194
242
|
end
|
195
243
|
end
|
@@ -6,62 +6,97 @@ module Spree
|
|
6
6
|
@order = order
|
7
7
|
end
|
8
8
|
|
9
|
-
# Get current line item for variant if exists
|
10
|
-
# Add variant qty to line_item
|
11
9
|
def add(variant, quantity = 1, currency = nil, shipment = nil)
|
12
|
-
line_item =
|
13
|
-
|
10
|
+
line_item = add_to_line_item(variant, quantity, currency, shipment)
|
11
|
+
reload_totals
|
12
|
+
PromotionHandler::Cart.new(order, line_item).activate
|
13
|
+
ItemAdjustments.new(line_item).update
|
14
|
+
reload_totals
|
15
|
+
line_item
|
14
16
|
end
|
15
17
|
|
16
|
-
# Get current line item for variant
|
17
|
-
# Remove variant qty from line_item
|
18
18
|
def remove(variant, quantity = 1, shipment = nil)
|
19
|
-
line_item =
|
19
|
+
line_item = remove_from_line_item(variant, quantity, shipment)
|
20
|
+
reload_totals
|
21
|
+
PromotionHandler::Cart.new(order, line_item).activate
|
22
|
+
ItemAdjustments.new(line_item).update
|
23
|
+
reload_totals
|
24
|
+
line_item
|
25
|
+
end
|
20
26
|
|
21
|
-
|
22
|
-
|
27
|
+
def update_cart(params)
|
28
|
+
if order.update_attributes(params)
|
29
|
+
order.line_items = order.line_items.select {|li| li.quantity > 0 }
|
30
|
+
# Update totals, then check if the order is eligible for any cart promotions.
|
31
|
+
# If we do not update first, then the item total will be wrong and ItemTotal
|
32
|
+
# promotion rules would not be triggered.
|
33
|
+
reload_totals
|
34
|
+
PromotionHandler::Cart.new(order).activate
|
35
|
+
order.ensure_updated_shipments
|
36
|
+
reload_totals
|
37
|
+
true
|
38
|
+
else
|
39
|
+
false
|
23
40
|
end
|
24
|
-
|
25
|
-
remove_from_line_item(line_item, variant, quantity, shipment)
|
26
41
|
end
|
27
42
|
|
28
43
|
private
|
44
|
+
def order_updater
|
45
|
+
@updater ||= OrderUpdater.new(order)
|
46
|
+
end
|
29
47
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
def reload_totals
|
49
|
+
order_updater.update_item_count
|
50
|
+
order_updater.update_item_total
|
51
|
+
order_updater.update_adjustment_total
|
52
|
+
order_updater.persist_totals
|
53
|
+
order.reload
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_to_line_item(variant, quantity, currency=nil, shipment=nil)
|
57
|
+
line_item = grab_line_item_by_variant(variant)
|
58
|
+
|
59
|
+
if line_item
|
60
|
+
line_item.target_shipment = shipment
|
61
|
+
line_item.quantity += quantity.to_i
|
39
62
|
line_item.currency = currency unless currency.nil?
|
40
|
-
line_item.price = variant.price_in(currency).amount
|
41
63
|
else
|
42
|
-
line_item
|
64
|
+
line_item = order.line_items.new(quantity: quantity, variant: variant)
|
65
|
+
line_item.target_shipment = shipment
|
66
|
+
if currency
|
67
|
+
line_item.currency = currency
|
68
|
+
line_item.price = variant.price_in(currency).amount
|
69
|
+
else
|
70
|
+
line_item.price = variant.price
|
71
|
+
end
|
43
72
|
end
|
73
|
+
|
74
|
+
line_item.save
|
75
|
+
line_item
|
44
76
|
end
|
45
77
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
78
|
+
def remove_from_line_item(variant, quantity, shipment=nil)
|
79
|
+
line_item = grab_line_item_by_variant(variant, true)
|
80
|
+
line_item.quantity += -quantity
|
81
|
+
line_item.target_shipment= shipment
|
50
82
|
|
51
|
-
|
52
|
-
|
53
|
-
|
83
|
+
if line_item.quantity == 0
|
84
|
+
line_item.destroy
|
85
|
+
else
|
86
|
+
line_item.save!
|
87
|
+
end
|
54
88
|
|
55
|
-
|
56
|
-
Spree::OrderInventory.new(order).verify(line_item, shipment)
|
57
|
-
line_item.destroy
|
58
|
-
else
|
59
|
-
line_item.save!
|
89
|
+
line_item
|
60
90
|
end
|
61
91
|
|
62
|
-
|
63
|
-
|
64
|
-
end
|
92
|
+
def grab_line_item_by_variant(variant, raise_error = false)
|
93
|
+
line_item = order.find_line_item_by_variant(variant)
|
65
94
|
|
95
|
+
if !line_item.present? && raise_error
|
96
|
+
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
|
97
|
+
end
|
98
|
+
|
99
|
+
line_item
|
100
|
+
end
|
66
101
|
end
|
67
102
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Spree
|
2
2
|
class OrderInventory
|
3
|
-
attr_accessor :order
|
3
|
+
attr_accessor :order, :line_item, :variant
|
4
4
|
|
5
|
-
def initialize(order)
|
5
|
+
def initialize(order, line_item)
|
6
6
|
@order = order
|
7
|
+
@line_item = line_item
|
8
|
+
@variant = line_item.variant
|
7
9
|
end
|
8
10
|
|
9
11
|
# Only verify inventory for completed orders (as orders in frontend checkout
|
@@ -13,98 +15,93 @@ module Spree
|
|
13
15
|
# In case shipment is passed the stock location should only unstock or
|
14
16
|
# restock items if the order is completed. That is so because stock items
|
15
17
|
# are always unstocked when the order is completed through +shipment.finalize+
|
16
|
-
def verify(
|
18
|
+
def verify(shipment = nil)
|
17
19
|
if order.completed? || shipment.present?
|
18
20
|
|
19
|
-
|
21
|
+
if inventory_units.size < line_item.quantity
|
22
|
+
quantity = line_item.quantity - inventory_units.size
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
add_to_shipment(shipment, line_item.variant, quantity)
|
26
|
-
elsif variant_units.size > line_item.quantity
|
27
|
-
remove(line_item, variant_units, shipment)
|
24
|
+
shipment = determine_target_shipment unless shipment
|
25
|
+
add_to_shipment(shipment, quantity)
|
26
|
+
elsif inventory_units.size > line_item.quantity
|
27
|
+
remove(inventory_units, shipment)
|
28
28
|
end
|
29
|
-
else
|
30
|
-
true
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
def
|
35
|
-
|
36
|
-
units.group_by(&:variant_id)[variant.id] || []
|
32
|
+
def inventory_units
|
33
|
+
line_item.inventory_units
|
37
34
|
end
|
38
35
|
|
39
36
|
private
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
def remove(item_units, shipment = nil)
|
38
|
+
quantity = item_units.size - line_item.quantity
|
39
|
+
|
40
|
+
if shipment.present?
|
41
|
+
remove_from_shipment(shipment, quantity)
|
42
|
+
else
|
43
|
+
order.shipments.each do |shipment|
|
44
|
+
break if quantity == 0
|
45
|
+
quantity -= remove_from_shipment(shipment, quantity)
|
46
|
+
end
|
49
47
|
end
|
50
48
|
end
|
51
|
-
end
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
50
|
+
# Returns either one of the shipment:
|
51
|
+
#
|
52
|
+
# first unshipped that already includes this variant
|
53
|
+
# first unshipped that's leaving from a stock_location that stocks this variant
|
54
|
+
def determine_target_shipment
|
55
|
+
shipment = order.shipments.detect do |shipment|
|
56
|
+
shipment.ready_or_pending? && shipment.include?(variant)
|
57
|
+
end
|
61
58
|
|
62
|
-
|
63
|
-
|
59
|
+
shipment ||= order.shipments.detect do |shipment|
|
60
|
+
shipment.ready_or_pending? && variant.stock_location_ids.include?(shipment.stock_location_id)
|
61
|
+
end
|
64
62
|
end
|
65
|
-
end
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
|
64
|
+
def add_to_shipment(shipment, quantity)
|
65
|
+
if variant.should_track_inventory?
|
66
|
+
on_hand, back_order = shipment.stock_location.fill_status(variant, quantity)
|
70
67
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
68
|
+
on_hand.times { shipment.set_up_inventory('on_hand', variant, order, line_item) }
|
69
|
+
back_order.times { shipment.set_up_inventory('backordered', variant, order, line_item) }
|
70
|
+
else
|
71
|
+
quantity.times { shipment.set_up_inventory('on_hand', variant, order, line_item) }
|
72
|
+
end
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
# adding to this shipment, and removing from stock_location
|
75
|
+
if order.completed?
|
76
|
+
shipment.stock_location.unstock(variant, quantity, shipment)
|
77
|
+
end
|
78
|
+
|
79
|
+
quantity
|
80
80
|
end
|
81
81
|
|
82
|
-
quantity
|
83
|
-
|
82
|
+
def remove_from_shipment(shipment, quantity)
|
83
|
+
return 0 if quantity == 0 || shipment.shipped?
|
84
84
|
|
85
|
-
|
86
|
-
|
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)
|
87
88
|
|
88
|
-
|
89
|
-
variant_unit.state == 'shipped'
|
90
|
-
end.sort_by(&:state)
|
89
|
+
removed_quantity = 0
|
91
90
|
|
92
|
-
|
91
|
+
shipment_units.each do |inventory_unit|
|
92
|
+
break if removed_quantity == quantity
|
93
|
+
inventory_unit.destroy
|
94
|
+
removed_quantity += 1
|
95
|
+
end
|
93
96
|
|
94
|
-
|
95
|
-
break if removed_quantity == quantity
|
96
|
-
inventory_unit.destroy
|
97
|
-
removed_quantity += 1
|
98
|
-
end
|
97
|
+
shipment.destroy if shipment.inventory_units.count == 0
|
99
98
|
|
100
|
-
|
99
|
+
# removing this from shipment, and adding to stock_location
|
100
|
+
if order.completed?
|
101
|
+
shipment.stock_location.restock variant, removed_quantity, shipment
|
102
|
+
end
|
101
103
|
|
102
|
-
|
103
|
-
if order.completed?
|
104
|
-
shipment.stock_location.restock variant, removed_quantity, shipment
|
104
|
+
removed_quantity
|
105
105
|
end
|
106
|
-
|
107
|
-
removed_quantity
|
108
|
-
end
|
109
106
|
end
|
110
107
|
end
|
@@ -9,23 +9,9 @@ module Spree
|
|
9
9
|
@errors = ActiveModel::Errors.new(self)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# * Single variant/quantity pairing
|
16
|
-
# +:variants => { variant_id => quantity }+
|
17
|
-
#
|
18
|
-
# * Multiple products at once
|
19
|
-
# +:products => { product_id => variant_id, product_id => variant_id }, :quantity => quantity+
|
20
|
-
def populate(from_hash)
|
21
|
-
from_hash[:products].each do |product_id,variant_id|
|
22
|
-
attempt_cart_add(variant_id, from_hash[:quantity])
|
23
|
-
end if from_hash[:products]
|
24
|
-
|
25
|
-
from_hash[:variants].each do |variant_id, quantity|
|
26
|
-
attempt_cart_add(variant_id, quantity)
|
27
|
-
end if from_hash[:variants]
|
28
|
-
|
12
|
+
|
13
|
+
def populate(variant_id, quantity)
|
14
|
+
attempt_cart_add(variant_id, quantity)
|
29
15
|
valid?
|
30
16
|
end
|
31
17
|
|
@@ -16,35 +16,23 @@ module Spree
|
|
16
16
|
# associations try to save and then in turn try to call +update!+ again.)
|
17
17
|
def update
|
18
18
|
update_totals
|
19
|
-
|
20
19
|
if order.completed?
|
21
20
|
update_payment_state
|
22
|
-
|
23
|
-
# give each of the shipments a chance to update themselves
|
24
|
-
shipments.each { |shipment| shipment.update!(order) }
|
21
|
+
update_shipments
|
25
22
|
update_shipment_state
|
26
23
|
end
|
27
|
-
|
28
|
-
update_adjustments
|
29
|
-
# update totals a second time in case updated adjustments have an effect on the total
|
30
|
-
update_totals
|
31
|
-
|
32
|
-
order.update_columns({
|
33
|
-
payment_state: order.payment_state,
|
34
|
-
shipment_state: order.shipment_state,
|
35
|
-
item_total: order.item_total,
|
36
|
-
adjustment_total: order.adjustment_total,
|
37
|
-
payment_total: order.payment_total,
|
38
|
-
total: order.total
|
39
|
-
})
|
40
|
-
|
41
24
|
run_hooks
|
25
|
+
persist_totals
|
42
26
|
end
|
43
27
|
|
44
28
|
def run_hooks
|
45
29
|
update_hooks.each { |hook| order.send hook }
|
46
30
|
end
|
47
31
|
|
32
|
+
def recalculate_adjustments
|
33
|
+
adjustments.includes(:source).each { |adjustment| adjustment.update! order }
|
34
|
+
end
|
35
|
+
|
48
36
|
# Updates the following Order total values:
|
49
37
|
#
|
50
38
|
# +payment_total+ The total value of all finalized Payments (NOTE: non-finalized Payments are excluded)
|
@@ -52,11 +40,61 @@ module Spree
|
|
52
40
|
# +adjustment_total+ The total value of all adjustments (promotions, credits, etc.)
|
53
41
|
# +total+ The so-called "order total." This is equivalent to +item_total+ plus +adjustment_total+.
|
54
42
|
def update_totals
|
55
|
-
order.payment_total = payments.completed.
|
43
|
+
order.payment_total = payments.completed.sum(:amount)
|
44
|
+
update_item_total
|
45
|
+
update_shipment_total
|
46
|
+
update_adjustment_total
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# give each of the shipments a chance to update themselves
|
51
|
+
def update_shipments
|
52
|
+
shipments.each { |shipment| shipment.update!(order) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_shipment_total
|
56
|
+
order.shipment_total = shipments.sum("cost + promo_total")
|
57
|
+
update_order_total
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_order_total
|
61
|
+
order.total = order.item_total + order.shipment_total + order.adjustment_total
|
62
|
+
end
|
63
|
+
|
64
|
+
def update_adjustment_total
|
65
|
+
recalculate_adjustments
|
66
|
+
order.adjustment_total = line_items.sum(:adjustment_total) +
|
67
|
+
shipments.sum(:adjustment_total) +
|
68
|
+
adjustments.eligible.sum(:amount)
|
69
|
+
order.included_tax_total = line_items.sum(:included_tax_total) + shipments.sum(:included_tax_total)
|
70
|
+
order.additional_tax_total = line_items.sum(:additional_tax_total) + shipments.sum(:additional_tax_total)
|
71
|
+
|
72
|
+
update_order_total
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_item_count
|
76
|
+
order.item_count = line_items.sum(:quantity)
|
77
|
+
end
|
78
|
+
|
79
|
+
def update_item_total
|
56
80
|
order.item_total = line_items.map(&:amount).sum
|
57
|
-
|
58
|
-
|
59
|
-
|
81
|
+
update_order_total
|
82
|
+
end
|
83
|
+
|
84
|
+
def persist_totals
|
85
|
+
order.update_columns(
|
86
|
+
payment_state: order.payment_state,
|
87
|
+
shipment_state: order.shipment_state,
|
88
|
+
item_total: order.item_total,
|
89
|
+
item_count: order.item_count,
|
90
|
+
adjustment_total: order.adjustment_total,
|
91
|
+
included_tax_total: order.included_tax_total,
|
92
|
+
additional_tax_total: order.additional_tax_total,
|
93
|
+
payment_total: order.payment_total,
|
94
|
+
shipment_total: order.shipment_total,
|
95
|
+
total: order.total,
|
96
|
+
updated_at: Time.now,
|
97
|
+
)
|
60
98
|
end
|
61
99
|
|
62
100
|
# Updates the +shipment_state+ attribute according to the following logic:
|
@@ -90,6 +128,7 @@ module Spree
|
|
90
128
|
end
|
91
129
|
|
92
130
|
order.state_changed('shipment')
|
131
|
+
order.shipment_state
|
93
132
|
end
|
94
133
|
|
95
134
|
# Updates the +payment_state+ attribute according to the following logic:
|
@@ -107,6 +146,8 @@ module Spree
|
|
107
146
|
if payments.present?
|
108
147
|
if payments.last.state == 'failed'
|
109
148
|
order.payment_state = 'failed'
|
149
|
+
elsif payments.last.state == 'checkout'
|
150
|
+
order.payment_state = 'pending'
|
110
151
|
elsif payments.last.state == 'completed'
|
111
152
|
order.payment_state = 'credit_owed'
|
112
153
|
else
|
@@ -124,30 +165,8 @@ module Spree
|
|
124
165
|
order.state_changed('payment')
|
125
166
|
end
|
126
167
|
|
127
|
-
# Updates each of the Order adjustments.
|
128
|
-
#
|
129
|
-
# This is intended to be called from an Observer so that the Order can
|
130
|
-
# respond to external changes to LineItem, Shipment, other Adjustments, etc.
|
131
|
-
#
|
132
|
-
# Adjustments will check if they are still eligible. Ineligible adjustments
|
133
|
-
# are preserved but not counted towards adjustment_total.
|
134
|
-
def update_adjustments
|
135
|
-
order.adjustments.reload.each { |adjustment| adjustment.update!(order) }
|
136
|
-
choose_best_promotion_adjustment
|
137
|
-
end
|
138
|
-
|
139
168
|
private
|
140
169
|
|
141
|
-
# Picks one (and only one) promotion to be eligible for this order
|
142
|
-
# This promotion provides the most discount, and if two promotions
|
143
|
-
# have the same amount, then it will pick the latest one.
|
144
|
-
def choose_best_promotion_adjustment
|
145
|
-
if best_promotion_adjustment = order.adjustments.promotion.eligible.reorder("amount ASC, created_at DESC").first
|
146
|
-
other_promotions = order.adjustments.promotion.where("id NOT IN (?)", best_promotion_adjustment.id)
|
147
|
-
other_promotions.update_all(eligible: false)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
170
|
def round_money(n)
|
152
171
|
(n * 100).round / 100.0
|
153
172
|
end
|