spree_core 2.1.12 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|