Class: Shoppe::Order
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Shoppe::Order
- Defined in:
- app/models/shoppe/order.rb,
app/models/shoppe/order/states.rb,
app/models/shoppe/order/actions.rb,
app/models/shoppe/order/billing.rb,
app/models/shoppe/order/delivery.rb
Constant Summary collapse
- STATUSES =
An array of all the available statuses for an order
['building', 'confirming', 'received', 'accepted', 'rejected', 'shipped']
Class Method Summary collapse
- .ransackable_associations(auth_object = nil) ⇒ Object
- .ransackable_attributes(auth_object = nil) ⇒ Object
Instance Method Summary collapse
-
#accept!(user) ⇒ Object
Mark order as accepted.
-
#accepted? ⇒ Boolean
Has this order been accepted?.
-
#accepter ⇒ Shoppe::User
The Shoppe::User who accepted the order.
-
#available_delivery_services ⇒ Array
An array of all the delivery services which are suitable for this order in it’s current state (based on its current weight).
-
#balance ⇒ BigDecimal
The total amount due on the order.
-
#billing_country ⇒ Shoppe::Country
The country which this order should be billed to.
-
#billing_name ⇒ String
The name for billing purposes.
-
#build_time ⇒ Float
The length of time the customer spent building the order before submitting it to us.
-
#building? ⇒ Boolean
Is this order still being built by the user?.
-
#confirm! ⇒ Boolean
This method should be executed by the application when the order should be completed by the customer.
-
#confirming? ⇒ Boolean
Is this order in the user confirmation step?.
-
#courier_tracking_url ⇒ String
The URL which can be used to track the delivery of this order.
-
#customer_name ⇒ String
The name of the customer in the format of “Company (First Last)” or if they don’t have company specified, just “First Last”.
-
#delivery_cost_price ⇒ BigDecimal
The cost of delivering this order in its current state.
-
#delivery_country ⇒ Shoppe::Country
The country where this order is being delivered to (if one has been provided).
-
#delivery_price ⇒ BigDecimal
The price for delivering this order in its current state.
-
#delivery_service ⇒ Shoppe::DeliveryService
The recommended delivery service for this order.
-
#delivery_service_price ⇒ BigDecimal
Return the delivery price for this order in its current state.
-
#delivery_service_prices ⇒ Array
An array of all the delivery service prices which can be applied to this order.
-
#delivery_tax_amount ⇒ BigDecimal
The tax amount due for the delivery of this order in its current state.
-
#delivery_tax_rate ⇒ BigDecimal
The tax rate for the delivery of this order in its current state.
-
#empty? ⇒ Boolean
Is this order empty? (i.e. doesn’t have any items associated with it).
-
#full_name ⇒ String
The full name of the customer created by concatinting the first & last name.
-
#has_items? ⇒ Boolean
Does this order have items?.
-
#invoiced? ⇒ Boolean
Is the order invoiced?.
-
#number ⇒ String
The order number.
-
#paid_in_full? ⇒ Boolean
Has this order been paid in full?.
-
#payment_outstanding? ⇒ Boolean
Is there a payment still outstanding on this order?.
-
#proceed_to_confirm(params = {}) ⇒ Boolean
This method should be called by the base application when the user has completed their first round of entering details.
-
#profit ⇒ BigDecimal
Return the price for the order.
-
#received? ⇒ Boolean
Has the order been received?.
-
#reject!(user) ⇒ Object
Mark order as rejected.
-
#rejected? ⇒ Boolean
Has this order been rejected?.
-
#rejecter ⇒ Shoppe::User
The Shoppe::User who rejected the order.
-
#remove_delivery_service_if_invalid ⇒ Object
Remove the associated delivery service if it’s invalid.
-
#ship!(user, consignment_number) ⇒ Object
Mark this order as shipped.
-
#shipped? ⇒ Boolean
Has this order been shipped?.
-
#shipper ⇒ Shoppe::User
The user who marked the order has shipped.
-
#tax ⇒ BigDecimal
The total amount of tax due on this order.
-
#total ⇒ BigDecimal
The total of the order including tax.
-
#total_before_tax ⇒ BigDecimal
The total price of the order before tax.
-
#total_cost ⇒ BigDecimal
The total cost of the order.
-
#total_items ⇒ Integer
Return the number of items in the order?.
-
#total_weight ⇒ BigDecimal
The total weight of the order.
-
#valid_delivery_service? ⇒ Boolean
Is the currently assigned delivery service appropriate for this order?.
Class Method Details
.ransackable_associations(auth_object = nil) ⇒ Object
87 88 89 |
# File 'app/models/shoppe/order.rb', line 87 def self.ransackable_associations(auth_object = nil) ['products'] end |
.ransackable_attributes(auth_object = nil) ⇒ Object
83 84 85 |
# File 'app/models/shoppe/order.rb', line 83 def self.ransackable_attributes(auth_object = nil) ["id", "billing_postcode", "billing_address1", "billing_address2", "billing_address3", "billing_address4", "first_name", "last_name", "company", "email_address", "phone_number", "consignment_number", "status", "received_at"] + _ransackers.keys end |
Instance Method Details
#accept!(user) ⇒ Object
Mark order as accepted
54 55 56 57 58 59 60 61 62 63 |
# File 'app/models/shoppe/order/actions.rb', line 54 def accept!(user) run_callbacks :acceptance do self.accepted_at = Time.now self.accepted_by = user.id self.status = 'accepted' self.save! self.order_items.each(&:accept!) Shoppe::OrderMailer.accepted(self).deliver end end |
#accepted? ⇒ Boolean
Has this order been accepted?
56 57 58 |
# File 'app/models/shoppe/order/states.rb', line 56 def accepted? !!self.accepted_at end |
#accepter ⇒ Shoppe::User
The Shoppe::User who accepted the order
10 |
# File 'app/models/shoppe/order/states.rb', line 10 belongs_to :accepter, :class_name => 'Shoppe::User', :foreign_key => 'accepted_by' |
#available_delivery_services ⇒ Array
An array of all the delivery services which are suitable for this order in it’s current state (based on its current weight)
93 94 95 96 97 |
# File 'app/models/shoppe/order/delivery.rb', line 93 def available_delivery_services @available_delivery_services ||= begin delivery_service_prices.map(&:delivery_service).uniq end end |
#balance ⇒ BigDecimal
The total amount due on the order
73 74 75 |
# File 'app/models/shoppe/order/billing.rb', line 73 def balance @balance ||= total - amount_paid end |
#billing_country ⇒ Shoppe::Country
The country which this order should be billed to
7 |
# File 'app/models/shoppe/order/billing.rb', line 7 belongs_to :billing_country, :class_name => 'Shoppe::Country', :foreign_key => 'billing_country_id' |
#billing_name ⇒ String
The name for billing purposes
26 27 28 |
# File 'app/models/shoppe/order/billing.rb', line 26 def billing_name company.blank? ? full_name : "#{full_name} (#{company})" end |
#build_time ⇒ Float
The length of time the customer spent building the order before submitting it to us. The time from first item in basket to received.
42 43 44 45 |
# File 'app/models/shoppe/order.rb', line 42 def build_time return nil if self.received_at.blank? self.created_at - self.received_at end |
#building? ⇒ Boolean
Is this order still being built by the user?
35 36 37 |
# File 'app/models/shoppe/order/states.rb', line 35 def building? self.status == 'building' end |
#confirm! ⇒ Boolean
This method should be executed by the application when the order should be completed by the customer. It will raise exceptions if anything goes wrong or return true if the order has been confirmed successfully
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'app/models/shoppe/order/actions.rb', line 28 def confirm! no_stock_of = self.order_items.select(&:validate_stock_levels) unless no_stock_of.empty? raise Shoppe::Errors::InsufficientStockToFulfil, :order => self, :out_of_stock_items => no_stock_of end run_callbacks :confirmation do # If we have successfully charged the card (i.e. no exception) we can go ahead and mark this # order as 'received' which means it can be accepted by staff. self.status = 'received' self.received_at = Time.now self.save! self.order_items.each(&:confirm!) # Send an email to the customer Shoppe::OrderMailer.received(self).deliver end # We're all good. true end |
#confirming? ⇒ Boolean
Is this order in the user confirmation step?
42 43 44 |
# File 'app/models/shoppe/order/states.rb', line 42 def confirming? self.status == 'confirming' end |
#courier_tracking_url ⇒ String
The URL which can be used to track the delivery of this order
178 179 180 181 |
# File 'app/models/shoppe/order/delivery.rb', line 178 def courier_tracking_url return nil if self.shipped_at.blank? || self.consignment_number.blank? @courier_tracking_url ||= self.delivery_service.tracking_url_for(self) end |
#customer_name ⇒ String
The name of the customer in the format of “Company (First Last)” or if they don’t have company specified, just “First Last”.
51 52 53 |
# File 'app/models/shoppe/order.rb', line 51 def customer_name company.blank? ? full_name : "#{company} (#{full_name})" end |
#delivery_cost_price ⇒ BigDecimal
The cost of delivering this order in its current state
134 135 136 |
# File 'app/models/shoppe/order/delivery.rb', line 134 def delivery_cost_price @delivery_cost_price ||= read_attribute(:delivery_cost_price) || delivery_service_price.try(:cost_price) || 0.0 end |
#delivery_country ⇒ Shoppe::Country
The country where this order is being delivered to (if one has been provided)
12 |
# File 'app/models/shoppe/order/delivery.rb', line 12 belongs_to :delivery_country, :class_name => 'Shoppe::Country', :foreign_key => 'delivery_country_id' |
#delivery_price ⇒ BigDecimal
The price for delivering this order in its current state
127 128 129 |
# File 'app/models/shoppe/order/delivery.rb', line 127 def delivery_price @delivery_price ||= read_attribute(:delivery_price) || delivery_service_price.try(:price) || 0.0 end |
#delivery_service ⇒ Shoppe::DeliveryService
The recommended delivery service for this order
7 |
# File 'app/models/shoppe/order/delivery.rb', line 7 belongs_to :delivery_service, :class_name => 'Shoppe::DeliveryService' |
#delivery_service_price ⇒ BigDecimal
Return the delivery price for this order in its current state
120 121 122 |
# File 'app/models/shoppe/order/delivery.rb', line 120 def delivery_service_price @delivery_service_price ||= self.delivery_service && self.delivery_service.delivery_service_prices.for_weight(self.total_weight).first end |
#delivery_service_prices ⇒ Array
An array of all the delivery service prices which can be applied to this order.
102 103 104 105 106 107 108 |
# File 'app/models/shoppe/order/delivery.rb', line 102 def delivery_service_prices @delivery_service_prices ||= begin 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 end end |
#delivery_tax_amount ⇒ BigDecimal
The tax amount due for the delivery of this order in its current state
141 142 143 144 145 146 147 |
# File 'app/models/shoppe/order/delivery.rb', line 141 def delivery_tax_amount @delivery_tax_amount ||= begin read_attribute(:delivery_tax_amount) || delivery_price / BigDecimal(100) * delivery_tax_rate || 0.0 end end |
#delivery_tax_rate ⇒ BigDecimal
The tax rate for the delivery of this order in its current state
152 153 154 155 156 157 158 |
# File 'app/models/shoppe/order/delivery.rb', line 152 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 end |
#empty? ⇒ Boolean
Is this order empty? (i.e. doesn’t have any items associated with it)
65 66 67 |
# File 'app/models/shoppe/order.rb', line 65 def empty? order_items.empty? end |
#full_name ⇒ String
The full name of the customer created by concatinting the first & last name
58 59 60 |
# File 'app/models/shoppe/order.rb', line 58 def full_name "#{first_name} #{last_name}" end |
#has_items? ⇒ Boolean
Does this order have items?
72 73 74 |
# File 'app/models/shoppe/order.rb', line 72 def has_items? total_items > 0 end |
#invoiced? ⇒ Boolean
Is the order invoiced?
94 95 96 |
# File 'app/models/shoppe/order/billing.rb', line 94 def invoiced? !invoice_number.blank? end |
#number ⇒ String
The order number
34 35 36 |
# File 'app/models/shoppe/order.rb', line 34 def number id.to_s.rjust(6, '0') end |
#paid_in_full? ⇒ Boolean
Has this order been paid in full?
87 88 89 |
# File 'app/models/shoppe/order/billing.rb', line 87 def paid_in_full? !payment_outstanding? end |
#payment_outstanding? ⇒ Boolean
Is there a payment still outstanding on this order?
80 81 82 |
# File 'app/models/shoppe/order/billing.rb', line 80 def payment_outstanding? balance > BigDecimal(0) end |
#proceed_to_confirm(params = {}) ⇒ Boolean
This method should be called by the base application when the user has completed their first round of entering details. This will mark the order as “confirming” which means the customer now just must confirm.
14 15 16 17 18 19 20 21 |
# File 'app/models/shoppe/order/actions.rb', line 14 def proceed_to_confirm(params = {}) self.status = 'confirming' if self.update(params) true else false end end |
#profit ⇒ BigDecimal
Return the price for the order
41 42 43 |
# File 'app/models/shoppe/order/billing.rb', line 41 def profit total_before_tax - total_cost end |
#received? ⇒ Boolean
Has the order been received?
63 64 65 |
# File 'app/models/shoppe/order/states.rb', line 63 def received? !!self.received_at? end |
#reject!(user) ⇒ Object
Mark order as rejected
68 69 70 71 72 73 74 75 76 77 |
# File 'app/models/shoppe/order/actions.rb', line 68 def reject!(user) run_callbacks :rejection do self.rejected_at = Time.now self.rejected_by = user.id self.status = 'rejected' self.save! self.order_items.each(&:reject!) Shoppe::OrderMailer.rejected(self).deliver end end |
#rejected? ⇒ Boolean
Has this order been rejected?
49 50 51 |
# File 'app/models/shoppe/order/states.rb', line 49 def rejected? !!self.rejected_at end |
#rejecter ⇒ Shoppe::User
The Shoppe::User who rejected the order
15 |
# File 'app/models/shoppe/order/states.rb', line 15 belongs_to :rejecter, :class_name => 'Shoppe::User', :foreign_key => 'rejected_by' |
#remove_delivery_service_if_invalid ⇒ Object
Remove the associated delivery service if it’s invalid
168 169 170 171 172 173 |
# File 'app/models/shoppe/order/delivery.rb', line 168 def remove_delivery_service_if_invalid unless self.valid_delivery_service? self.delivery_service = nil self.save end end |
#ship!(user, consignment_number) ⇒ Object
Mark this order as shipped
184 185 186 187 188 189 190 191 192 193 |
# File 'app/models/shoppe/order/delivery.rb', line 184 def ship!(user, consignment_number) run_callbacks :ship do self.shipped_at = Time.now self.shipped_by = user.id self.status = 'shipped' self.consignment_number = consignment_number self.save! Shoppe::OrderMailer.shipped(self).deliver end end |
#shipped? ⇒ Boolean
Has this order been shipped?
78 79 80 |
# File 'app/models/shoppe/order/delivery.rb', line 78 def shipped? !!self.shipped_at? end |
#shipper ⇒ Shoppe::User
The user who marked the order has shipped
17 |
# File 'app/models/shoppe/order/delivery.rb', line 17 belongs_to :shipper, :class_name => 'Shoppe::User', :foreign_key => 'shipped_by' |
#tax ⇒ BigDecimal
The total amount of tax due on this order
56 57 58 59 |
# File 'app/models/shoppe/order/billing.rb', line 56 def tax self.delivery_tax_amount + order_items.inject(BigDecimal(0)) { |t, i| t + i.tax_amount } end |
#total ⇒ BigDecimal
The total of the order including tax
64 65 66 67 68 |
# File 'app/models/shoppe/order/billing.rb', line 64 def total self.delivery_price + self.delivery_tax_amount + order_items.inject(BigDecimal(0)) { |t, i| t + i.total } end |
#total_before_tax ⇒ BigDecimal
The total price of the order before tax
48 49 50 51 |
# File 'app/models/shoppe/order/billing.rb', line 48 def total_before_tax self.delivery_price + order_items.inject(BigDecimal(0)) { |t, i| t + i.sub_total } end |
#total_cost ⇒ BigDecimal
The total cost of the order
33 34 35 36 |
# File 'app/models/shoppe/order/billing.rb', line 33 def total_cost self.delivery_cost_price + order_items.inject(BigDecimal(0)) { |t, i| t + i.total_cost } end |
#total_items ⇒ Integer
Return the number of items in the order?
79 80 81 |
# File 'app/models/shoppe/order.rb', line 79 def total_items @total_items ||= order_items.inject(0) { |t,i| t + i.quantity } end |
#total_weight ⇒ BigDecimal
The total weight of the order
85 86 87 |
# File 'app/models/shoppe/order/delivery.rb', line 85 def total_weight order_items.inject(BigDecimal(0)) { |t,i| t + i.weight} end |
#valid_delivery_service? ⇒ Boolean
Is the currently assigned delivery service appropriate for this order?
163 164 165 |
# File 'app/models/shoppe/order/delivery.rb', line 163 def valid_delivery_service? self.delivery_service && self.available_delivery_services.include?(self.delivery_service) end |