app/models/shoppe/order/delivery.rb in shoppe-0.0.19 vs app/models/shoppe/order/delivery.rb in shoppe-0.0.20
- old
+ new
@@ -26,18 +26,19 @@
order.validates :delivery_address3, :presence => true
order.validates :delivery_address4, :presence => true
order.validates :delivery_postcode, :presence => true
order.validates :delivery_country, :presence => true
end
+
validate do
if self.delivery_required?
if self.delivery_service.nil?
errors.add :delivery_service_id, "must be specified"
return
end
- if self.delivery_service && !available_delivery_services.include?(self.delivery_service)
+ unless self.valid_delivery_service?
errors.add :delivery_service_id, "is not suitable for this order"
end
end
end
@@ -45,18 +46,22 @@
# Ensure that before we confirm the order that the delivery service which has been selected
# is appropritae for the contents of the order.
if self.delivery_required? && !self.valid_delivery_service?
raise Shoppe::Errors::InappropriateDeliveryService, :order => self
end
-
- # Store the delivery prices with the order
- if self.delivery_service
- write_attribute :delivery_service_id, self.delivery_service.id
- write_attribute :delivery_price, self.delivery_price
- write_attribute :delivery_cost_price, self.delivery_cost_price
- write_attribute :delivery_tax_amount, self.delivery_tax_amount
- write_attribute :delivery_tax_rate, self.delivery_tax_rate
+ cache_delivery_pricing
+ end
+
+ # If an order has been received and something changes the delivery service or the delivery price
+ # is cleared, we will re-cache all the delivery pricing so that we have the latest.
+ before_save do
+ if received? && (delivery_service_id_changed? || (self.delivery_price_changed? && read_attribute(:delivery_price).blank?))
+ self.delivery_price = nil
+ self.delivery_cost_price = nil
+ self.delivery_tax_rate = nil
+ self.delivery_tax_amount = nil
+ cache_delivery_pricing
end
end
# If there isn't a seperate address needed, clear all the fields back to nil
before_validation do
@@ -77,10 +82,32 @@
define_method(f) do
separate_delivery_address? ? super() : send(f.to_s.gsub('delivery_', 'billing_'))
end
end
+ # Cache delivery prices for the order
+ def cache_delivery_pricing
+ if self.delivery_service
+ write_attribute :delivery_service_id, self.delivery_service.id
+ write_attribute :delivery_price, self.delivery_price
+ write_attribute :delivery_cost_price, self.delivery_cost_price
+ write_attribute :delivery_tax_rate, self.delivery_tax_rate
+ else
+ write_attribute :delivery_service_id, nil
+ write_attribute :delivery_price, nil
+ write_attribute :delivery_cost_price, nil
+ write_attribute :delivery_tax_rate, nil
+ write_attribute :delivery_tax_amount, nil
+ end
+ end
+
+ # Cache prices and save the order
+ def cache_delivery_pricing!
+ cache_delivery_pricing
+ save!
+ end
+
# Has this order been shipped?
#
# @return [Boolean]
def shipped?
!!self.shipped_at?
@@ -88,11 +115,11 @@
# The total weight of the order
#
# @return [BigDecimal]
def total_weight
- order_items.inject(BigDecimal(0)) { |t,i| t + i.weight}
+ order_items.inject(BigDecimal(0)) { |t,i| t + i.total_weight}
end
# Is delivery required for this order?
#
# @return [Boolean]
@@ -103,27 +130,24 @@
# An array of all the delivery services which are suitable for this order in it's
# current state (based on its current weight)
#
# @return [Array] an array of Shoppe::DeliveryService objects
def available_delivery_services
- @available_delivery_services ||= begin
- delivery_service_prices.map(&:delivery_service).uniq
- end
+ delivery_service_prices.map(&:delivery_service).uniq
end
# An array of all the delivery service prices which can be applied to this order.
#
# @return [Array] an array of Shoppe:DeliveryServicePrice objects
def delivery_service_prices
- @delivery_service_prices ||= begin
- if delivery_required?
- prices = Shoppe::DeliveryServicePrice.joins(:delivery_service).where(:shoppe_delivery_services => {:active => true}).order("`default` desc, price asc").for_weight(total_weight)
- prices = prices.select { |p| p.countries.empty? || p.country?(self.delivery_country) }
- prices
- else
- []
- end
+ if delivery_required?
+ prices = Shoppe::DeliveryServicePrice.joins(:delivery_service).where(:shoppe_delivery_services => {:active => true}).order(:price).for_weight(total_weight)
+ prices = prices.select { |p| p.countries.empty? || p.country?(self.delivery_country) }
+ prices = prices.group_by { |dsp| dsp.delivery_service.default? }
+ (prices[true] || []) | (prices[false] || [])
+ else
+ []
end
end
# The recommended delivery service for this order
#
@@ -134,54 +158,49 @@
# Return the delivery price for this order in its current state
#
# @return [BigDecimal]
def delivery_service_price
- @delivery_service_price ||= self.delivery_service && self.delivery_service.delivery_service_prices.for_weight(self.total_weight).first
+ self.delivery_service && self.delivery_service.delivery_service_prices.for_weight(self.total_weight).first
end
# The price for delivering this order in its current state
#
# @return [BigDecimal]
def delivery_price
- @delivery_price ||= read_attribute(:delivery_price) || delivery_service_price.try(:price) || 0.0
+ read_attribute(:delivery_price) || delivery_service_price.try(:price) || BigDecimal(0)
end
# The cost of delivering this order in its current state
#
# @return [BigDecimal]
def delivery_cost_price
- @delivery_cost_price ||= read_attribute(:delivery_cost_price) || delivery_service_price.try(:cost_price) || 0.0
+ read_attribute(:delivery_cost_price) || delivery_service_price.try(:cost_price) || BigDecimal(0)
end
# The tax amount due for the delivery of this order in its current state
#
# @return [BigDecimal]
def delivery_tax_amount
- @delivery_tax_amount ||= begin
- read_attribute(:delivery_tax_amount) ||
- delivery_price / BigDecimal(100) * delivery_tax_rate ||
- 0.0
- end
+ read_attribute(:delivery_tax_amount) ||
+ delivery_price / BigDecimal(100) * delivery_tax_rate
end
# The tax rate for the delivery of this order in its current state
#
# @return [BigDecimal]
def delivery_tax_rate
- @delivery_tax_rate ||= begin
- read_attribute(:delivery_tax_rate) ||
- delivery_service_price.try(:tax_rate).try(:rate_for, self) ||
- 0.0
- end
+ read_attribute(:delivery_tax_rate) ||
+ delivery_service_price.try(:tax_rate).try(:rate_for, self) ||
+ BigDecimal(0)
end
# Is the currently assigned delivery service appropriate for this order?
#
# @return [Boolean]
def valid_delivery_service?
- self.delivery_service && self.available_delivery_services.include?(self.delivery_service)
+ self.delivery_service ? self.available_delivery_services.include?(self.delivery_service) : !self.delivery_required?
end
# Remove the associated delivery service if it's invalid
def remove_delivery_service_if_invalid
unless self.valid_delivery_service?
@@ -197,13 +216,13 @@
return nil if self.shipped_at.blank? || self.consignment_number.blank?
@courier_tracking_url ||= self.delivery_service.tracking_url_for(self)
end
# Mark this order as shipped
- def ship!(user, consignment_number)
+ def ship!(consignment_number, user = nil)
run_callbacks :ship do
self.shipped_at = Time.now
- self.shipped_by = user.id
+ self.shipper = user if user
self.status = 'shipped'
self.consignment_number = consignment_number
self.save!
Shoppe::OrderMailer.shipped(self).deliver
end