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
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spree
|
2
|
+
module PromotionHandler
|
3
|
+
class Page
|
4
|
+
attr_reader :order, :path
|
5
|
+
|
6
|
+
def initialize(order, path)
|
7
|
+
@order = order
|
8
|
+
@path = path.gsub(/\A\//, '')
|
9
|
+
end
|
10
|
+
|
11
|
+
def activate
|
12
|
+
if promotion && promotion.eligible?(order)
|
13
|
+
promotion.activate(:order => order)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def promotion
|
20
|
+
@promotion ||= Promotion.active.find_by(:path => path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,23 +1,31 @@
|
|
1
1
|
# Base class for all promotion rules
|
2
2
|
module Spree
|
3
3
|
class PromotionRule < ActiveRecord::Base
|
4
|
-
belongs_to :promotion,
|
4
|
+
belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_rules
|
5
5
|
|
6
6
|
scope :of_type, ->(t) { where(type: t) }
|
7
7
|
|
8
8
|
validate :promotion, presence: true
|
9
|
-
validate :
|
9
|
+
validate :unique_per_promotion, on: :create
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def self.for(promotable)
|
12
|
+
all.select { |rule| rule.applicable?(promotable) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def applicable?(promotable)
|
16
|
+
raise 'applicable? should be implemented in a sub-class of Spree::PromotionRule'
|
17
|
+
end
|
18
|
+
|
19
|
+
def eligible?(promotable, options = {})
|
20
|
+
raise 'eligible? should be implemented in a sub-class of Spree::PromotionRule'
|
13
21
|
end
|
14
22
|
|
15
23
|
private
|
16
|
-
def
|
17
|
-
if Spree::PromotionRule.exists?(
|
24
|
+
def unique_per_promotion
|
25
|
+
if Spree::PromotionRule.exists?(promotion_id: promotion_id, type: self.class.name)
|
18
26
|
errors[:base] << "Promotion already contains this rule type"
|
19
27
|
end
|
20
28
|
end
|
21
|
-
|
29
|
+
|
22
30
|
end
|
23
31
|
end
|
@@ -2,7 +2,7 @@ module Spree
|
|
2
2
|
class Property < ActiveRecord::Base
|
3
3
|
has_and_belongs_to_many :prototypes, join_table: 'spree_properties_prototypes'
|
4
4
|
|
5
|
-
has_many :product_properties, dependent: :delete_all
|
5
|
+
has_many :product_properties, dependent: :delete_all, inverse_of: :property
|
6
6
|
has_many :products, through: :product_properties
|
7
7
|
|
8
8
|
validates :name, :presentation, presence: true
|
@@ -62,6 +62,11 @@ module Spree
|
|
62
62
|
order.shipped_shipments.collect{|s| s.inventory_units.to_a}.flatten
|
63
63
|
end
|
64
64
|
|
65
|
+
# Used when Adjustment#update! wants to update the related adjustmenrt
|
66
|
+
def compute_amount(*args)
|
67
|
+
amount.abs * -1
|
68
|
+
end
|
69
|
+
|
65
70
|
private
|
66
71
|
|
67
72
|
def must_have_shipped_units
|
@@ -82,10 +87,11 @@ module Spree
|
|
82
87
|
Spree::StockMovement.create!(stock_item_id: stock_item.id, quantity: 1)
|
83
88
|
end
|
84
89
|
|
85
|
-
credit = Adjustment.new(amount:
|
90
|
+
credit = Adjustment.new(amount: compute_amount, label: Spree.t(:rma_credit))
|
86
91
|
credit.source = self
|
87
92
|
credit.adjustable = order
|
88
93
|
credit.save
|
94
|
+
order.update!
|
89
95
|
|
90
96
|
order.return if inventory_units.all?(&:returned?)
|
91
97
|
end
|
@@ -2,17 +2,19 @@ require 'ostruct'
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class Shipment < ActiveRecord::Base
|
5
|
-
belongs_to :order, class_name: 'Spree::Order', touch: true
|
6
|
-
belongs_to :address, class_name: 'Spree::Address'
|
5
|
+
belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments
|
6
|
+
belongs_to :address, class_name: 'Spree::Address', inverse_of: :shipments
|
7
7
|
belongs_to :stock_location, class_name: 'Spree::StockLocation'
|
8
8
|
|
9
9
|
has_many :shipping_rates, dependent: :delete_all
|
10
10
|
has_many :shipping_methods, through: :shipping_rates
|
11
11
|
has_many :state_changes, as: :stateful
|
12
|
-
has_many :inventory_units, dependent: :delete_all
|
13
|
-
|
12
|
+
has_many :inventory_units, dependent: :delete_all, inverse_of: :shipment
|
13
|
+
has_many :adjustments, as: :adjustable, dependent: :delete_all
|
14
14
|
|
15
|
-
after_save :
|
15
|
+
after_save :update_adjustments
|
16
|
+
|
17
|
+
before_validation :set_cost_zero_when_nil
|
16
18
|
|
17
19
|
attr_accessor :special_instructions
|
18
20
|
|
@@ -60,6 +62,14 @@ module Spree
|
|
60
62
|
transition from: :canceled, to: :pending
|
61
63
|
end
|
62
64
|
after_transition from: :canceled, to: [:pending, :ready], do: :after_resume
|
65
|
+
|
66
|
+
after_transition do |shipment, transition|
|
67
|
+
shipment.state_changes.create!(
|
68
|
+
previous_state: transition.from,
|
69
|
+
next_state: transition.to,
|
70
|
+
name: 'shipment',
|
71
|
+
)
|
72
|
+
end
|
63
73
|
end
|
64
74
|
|
65
75
|
def to_param
|
@@ -70,6 +80,10 @@ module Spree
|
|
70
80
|
inventory_units.any? { |inventory_unit| inventory_unit.backordered? }
|
71
81
|
end
|
72
82
|
|
83
|
+
def ready_or_pending?
|
84
|
+
self.ready? || self.pending?
|
85
|
+
end
|
86
|
+
|
73
87
|
def shipped=(value)
|
74
88
|
return unless value == '1' && shipped_at.nil?
|
75
89
|
self.shipped_at = Time.now
|
@@ -97,6 +111,10 @@ module Spree
|
|
97
111
|
self.save!
|
98
112
|
end
|
99
113
|
|
114
|
+
def tax_category
|
115
|
+
selected_shipping_rate.try(:tax_rate).try(:tax_category)
|
116
|
+
end
|
117
|
+
|
100
118
|
def refresh_rates
|
101
119
|
return shipping_rates if shipped?
|
102
120
|
return [] unless can_get_rates?
|
@@ -120,54 +138,59 @@ module Spree
|
|
120
138
|
order ? order.currency : Spree::Config[:currency]
|
121
139
|
end
|
122
140
|
|
123
|
-
# The adjustment amount associated with this shipment (if any.) Returns only the first adjustment to match
|
124
|
-
# the shipment but there should never really be more than one.
|
125
|
-
def cost
|
126
|
-
adjustment ? adjustment.amount : 0
|
127
|
-
end
|
128
|
-
|
129
|
-
alias_method :amount, :cost
|
130
|
-
|
131
141
|
def display_cost
|
132
142
|
Spree::Money.new(cost, { currency: currency })
|
133
143
|
end
|
134
|
-
|
135
|
-
alias_method :display_amount, :display_cost
|
144
|
+
alias display_amount display_cost
|
136
145
|
|
137
146
|
def item_cost
|
138
147
|
line_items.map(&:amount).sum
|
139
148
|
end
|
140
149
|
|
141
|
-
def
|
142
|
-
|
150
|
+
def discounted_cost
|
151
|
+
cost + promo_total
|
152
|
+
end
|
153
|
+
alias discounted_amount discounted_cost
|
154
|
+
|
155
|
+
# Only one of either included_tax_total or additional_tax_total is set
|
156
|
+
# This method returns the total of the two. Saves having to check if
|
157
|
+
# tax is included or additional.
|
158
|
+
def tax_total
|
159
|
+
included_tax_total + additional_tax_total
|
160
|
+
end
|
161
|
+
|
162
|
+
def final_price
|
163
|
+
discounted_cost + tax_total
|
143
164
|
end
|
144
165
|
|
145
|
-
def
|
146
|
-
|
166
|
+
def display_discounted_cost
|
167
|
+
Spree::Money.new(discounted_cost, { currency: currency })
|
147
168
|
end
|
148
169
|
|
149
|
-
def
|
150
|
-
Spree::Money.new(
|
170
|
+
def display_item_cost
|
171
|
+
Spree::Money.new(item_cost, { currency: currency })
|
151
172
|
end
|
152
173
|
|
153
174
|
def editable_by?(user)
|
154
175
|
!shipped?
|
155
176
|
end
|
156
177
|
|
178
|
+
ManifestItem = Struct.new(:line_item, :variant, :quantity, :states)
|
179
|
+
|
157
180
|
def manifest
|
158
181
|
inventory_units.group_by(&:variant).map do |variant, units|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
182
|
+
units.group_by(&:line_item).map do |line_item, units|
|
183
|
+
|
184
|
+
states = {}
|
185
|
+
units.group_by(&:state).each { |state, iu| states[state] = iu.count }
|
186
|
+
|
187
|
+
ManifestItem.new(line_item, variant, units.length, states)
|
188
|
+
end
|
189
|
+
end.flatten
|
163
190
|
end
|
164
191
|
|
165
192
|
def line_items
|
166
|
-
|
167
|
-
order.line_items.select { |li| !li.should_track_inventory? || inventory_units.pluck(:variant_id).include?(li.variant_id) }
|
168
|
-
else
|
169
|
-
order.line_items
|
170
|
-
end
|
193
|
+
inventory_units.includes(:line_item).map(&:line_item).uniq
|
171
194
|
end
|
172
195
|
|
173
196
|
def finalize!
|
@@ -189,7 +212,10 @@ module Spree
|
|
189
212
|
def update!(order)
|
190
213
|
old_state = state
|
191
214
|
new_state = determine_state(order)
|
192
|
-
|
215
|
+
update_columns(
|
216
|
+
state: new_state,
|
217
|
+
updated_at: Time.now,
|
218
|
+
)
|
193
219
|
after_ship if new_state == 'shipped' and old_state != 'shipped'
|
194
220
|
end
|
195
221
|
|
@@ -215,19 +241,45 @@ module Spree
|
|
215
241
|
end
|
216
242
|
|
217
243
|
def inventory_units_for(variant)
|
218
|
-
inventory_units.
|
244
|
+
inventory_units.where(variant_id: variant.id)
|
245
|
+
end
|
246
|
+
|
247
|
+
def inventory_units_for_item(line_item, variant = nil)
|
248
|
+
inventory_units.where(line_item_id: line_item.id, variant_id: line_item.variant.id || variant.id)
|
219
249
|
end
|
220
250
|
|
221
251
|
def to_package
|
222
252
|
package = Stock::Package.new(stock_location, order)
|
223
|
-
inventory_units.includes(:
|
224
|
-
|
253
|
+
grouped_inventory_units = inventory_units.includes(:line_item).group_by do |iu|
|
254
|
+
[iu.line_item, iu.state_name]
|
255
|
+
end
|
256
|
+
|
257
|
+
grouped_inventory_units.each do |(line_item, state_name), inventory_units|
|
258
|
+
package.add line_item, inventory_units.count, state_name
|
225
259
|
end
|
226
260
|
package
|
227
261
|
end
|
228
262
|
|
229
|
-
def set_up_inventory(state, variant, order)
|
230
|
-
self.inventory_units.create(
|
263
|
+
def set_up_inventory(state, variant, order, line_item)
|
264
|
+
self.inventory_units.create(
|
265
|
+
state: state,
|
266
|
+
variant_id: variant.id,
|
267
|
+
order_id: order.id,
|
268
|
+
line_item_id: line_item.id
|
269
|
+
)
|
270
|
+
end
|
271
|
+
|
272
|
+
def persist_cost
|
273
|
+
self.cost = selected_shipping_rate.cost
|
274
|
+
update_amounts
|
275
|
+
end
|
276
|
+
|
277
|
+
def update_amounts
|
278
|
+
self.update_columns(
|
279
|
+
cost: selected_shipping_rate.cost,
|
280
|
+
adjustment_total: adjustments.map(&:update!).compact.sum,
|
281
|
+
updated_at: Time.now,
|
282
|
+
)
|
231
283
|
end
|
232
284
|
|
233
285
|
private
|
@@ -250,32 +302,44 @@ module Spree
|
|
250
302
|
"#{Spree.t(:shipping)} (#{shipping_method.name})"
|
251
303
|
end
|
252
304
|
|
305
|
+
def validate_shipping_method
|
306
|
+
unless shipping_method.nil?
|
307
|
+
errors.add :shipping_method, Spree.t(:is_not_available_to_shipment_address) unless shipping_method.include?(address)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
253
311
|
def after_ship
|
254
312
|
inventory_units.each &:ship!
|
255
|
-
adjustment.finalize!
|
256
313
|
send_shipped_email
|
257
314
|
touch :shipped_at
|
315
|
+
update_order_shipment_state
|
316
|
+
end
|
317
|
+
|
318
|
+
def update_order_shipment_state
|
319
|
+
new_state = OrderUpdater.new(order).update_shipment_state
|
320
|
+
order.update_columns(
|
321
|
+
shipment_state: new_state,
|
322
|
+
updated_at: Time.now,
|
323
|
+
)
|
258
324
|
end
|
259
325
|
|
260
326
|
def send_shipped_email
|
261
327
|
ShipmentMailer.shipped_email(self.id).deliver
|
262
328
|
end
|
263
329
|
|
264
|
-
def
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
shipping_method.create_adjustment shipping_method.adjustment_label, order, self, true, "open"
|
273
|
-
reload #ensure adjustment is present on later saves
|
330
|
+
def set_cost_zero_when_nil
|
331
|
+
self.cost = 0 unless self.cost
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
def update_adjustments
|
336
|
+
if cost_changed? && state != 'shipped'
|
337
|
+
recalculate_adjustments
|
274
338
|
end
|
275
339
|
end
|
276
340
|
|
277
|
-
def
|
278
|
-
|
341
|
+
def recalculate_adjustments
|
342
|
+
Spree::ItemAdjustments.new(self).update
|
279
343
|
end
|
280
344
|
|
281
345
|
def can_get_rates?
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module Spree
|
2
2
|
class ShippingCalculator < Calculator
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
compute_package package
|
3
|
+
|
4
|
+
def compute_shipment(shipment)
|
5
|
+
raise NotImplementedError, "Please implement 'compute_shipment(shipment)' in your calculator: #{self.class.name}"
|
7
6
|
end
|
8
7
|
|
9
8
|
def compute_package(package)
|
10
|
-
raise
|
9
|
+
raise NotImplementedError, "Please implement 'compute_package(package)' in your calculator: #{self.class.name}"
|
11
10
|
end
|
12
11
|
|
13
12
|
def available?(package)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Spree
|
2
2
|
class ShippingCategory < ActiveRecord::Base
|
3
3
|
validates :name, presence: true
|
4
|
-
has_many :products
|
4
|
+
has_many :products, inverse_of: :shipping_category
|
5
5
|
has_many :shipping_method_categories
|
6
6
|
has_many :shipping_methods, through: :shipping_method_categories
|
7
7
|
end
|
8
|
-
end
|
8
|
+
end
|
@@ -1,28 +1,26 @@
|
|
1
1
|
module Spree
|
2
2
|
class ShippingMethod < ActiveRecord::Base
|
3
|
-
acts_as_paranoid
|
4
3
|
include Spree::Core::CalculatedAdjustments
|
5
4
|
DISPLAY = [:both, :front_end, :back_end]
|
6
5
|
|
7
6
|
default_scope -> { where(deleted_at: nil) }
|
8
7
|
|
8
|
+
has_many :adjustments, as: :source
|
9
|
+
has_many :shipments
|
9
10
|
has_many :shipping_method_categories, :dependent => :destroy
|
10
11
|
has_many :shipping_categories, through: :shipping_method_categories
|
11
12
|
has_many :shipping_rates, inverse_of: :shipping_method
|
12
|
-
has_many :shipments, :through => :shipping_rates
|
13
13
|
|
14
14
|
has_and_belongs_to_many :zones, :join_table => 'spree_shipping_methods_zones',
|
15
15
|
:class_name => 'Spree::Zone',
|
16
16
|
:foreign_key => 'shipping_method_id'
|
17
17
|
|
18
|
+
belongs_to :tax_category, :class_name => 'Spree::TaxCategory'
|
19
|
+
|
18
20
|
validates :name, presence: true
|
19
21
|
|
20
22
|
validate :at_least_one_shipping_category
|
21
23
|
|
22
|
-
def adjustment_label
|
23
|
-
Spree.t(:shipping)
|
24
|
-
end
|
25
|
-
|
26
24
|
def include?(address)
|
27
25
|
return false unless address
|
28
26
|
zones.any? do |zone|
|
@@ -44,7 +42,15 @@ module Spree
|
|
44
42
|
self.display_on != "back_end"
|
45
43
|
end
|
46
44
|
|
45
|
+
def tax_category
|
46
|
+
Spree::TaxCategory.unscoped { super }
|
47
|
+
end
|
48
|
+
|
47
49
|
private
|
50
|
+
def compute_amount(calculable)
|
51
|
+
self.calculator.compute(calculable)
|
52
|
+
end
|
53
|
+
|
48
54
|
def at_least_one_shipping_category
|
49
55
|
if self.shipping_categories.empty?
|
50
56
|
self.errors[:base] << "You need to select at least one shipping category"
|
@@ -2,24 +2,44 @@ module Spree
|
|
2
2
|
class ShippingRate < ActiveRecord::Base
|
3
3
|
belongs_to :shipment, class_name: 'Spree::Shipment'
|
4
4
|
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
|
5
|
+
belongs_to :tax_rate, class_name: 'Spree::TaxRate'
|
6
|
+
|
7
|
+
scope :with_shipping_method,
|
8
|
+
-> { includes(:shipping_method).
|
9
|
+
references(:shipping_method).
|
10
|
+
order("cost ASC") }
|
5
11
|
|
6
12
|
delegate :order, :currency, to: :shipment
|
7
13
|
delegate :name, to: :shipping_method
|
8
14
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
price = cost
|
14
|
-
end
|
15
|
+
def display_base_price
|
16
|
+
Spree::Money.new(cost, currency: currency)
|
17
|
+
end
|
15
18
|
|
16
|
-
|
19
|
+
def display_tax_amount
|
20
|
+
Spree::Money.new(tax_rate.calculator.compute_shipping_rate(self), currency: currency)
|
17
21
|
end
|
18
22
|
|
23
|
+
def display_price
|
24
|
+
price = display_base_price.to_s
|
25
|
+
if tax_rate
|
26
|
+
amount = "#{display_tax_amount} #{tax_rate.name}"
|
27
|
+
if tax_rate.included_in_price?
|
28
|
+
price += " (incl. #{amount})"
|
29
|
+
else
|
30
|
+
price += " (+ #{amount})"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
price
|
34
|
+
end
|
19
35
|
alias_method :display_cost, :display_price
|
20
36
|
|
21
37
|
def shipping_method
|
22
38
|
Spree::ShippingMethod.unscoped { super }
|
23
39
|
end
|
40
|
+
|
41
|
+
def tax_rate
|
42
|
+
Spree::TaxRate.unscoped { super }
|
43
|
+
end
|
24
44
|
end
|
25
45
|
end
|