Class: Spina::Shop::Order
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Spina::Shop::Order
- Includes:
- Statesman::Adapters::ActiveRecordQueries
- Defined in:
- app/models/spina/shop/order.rb,
app/models/spina/shop/order/billing.rb,
app/models/spina/shop/order/state_machine_transitions.rb
Instance Attribute Summary collapse
-
#password ⇒ Object
Returns the value of attribute password.
-
#validate_delivery ⇒ Object
Returns the value of attribute validate_delivery.
-
#validate_details ⇒ Object
Returns the value of attribute validate_details.
-
#validate_payment ⇒ Object
Returns the value of attribute validate_payment.
-
#validate_stock ⇒ Object
Returns the value of attribute validate_stock.
Class Method Summary collapse
Instance Method Summary collapse
- #age ⇒ Object
- #apply_gift_card! ⇒ Object
- #assign_address(address, address_type:) ⇒ Object
- #billing_address ⇒ Object
- #billing_first_name ⇒ Object
- #billing_last_name ⇒ Object
- #billing_name ⇒ Object
- #building? ⇒ Boolean
- #cancelled? ⇒ Boolean
- #confirmed? ⇒ Boolean
- #confirming? ⇒ Boolean
- #delivered? ⇒ Boolean
- #delivery_address ⇒ Object
- #delivery_options ⇒ Object
- #delivery_price ⇒ Object
- #delivery_tax_modifier ⇒ Object
- #delivery_tax_rate ⇒ Object
- #duplicate! ⇒ Object
- #empty? ⇒ Boolean
- #everything_valid? ⇒ Boolean
- #failed? ⇒ Boolean
- #gift_card_amount ⇒ Object
- #merge!(order) ⇒ Object
- #nothing_owed? ⇒ Boolean
-
#number ⇒ Object
Order number with zeroes.
- #of_age? ⇒ Boolean
- #order_prepared? ⇒ Boolean
- #order_total ⇒ Object
- #paid? ⇒ Boolean
- #picked_up? ⇒ Boolean
-
#prices_include_tax ⇒ Object
If VAT is reverse charged, all prices must be excluding VAT.
- #products ⇒ Object
- #received? ⇒ Boolean
- #remove_gift_card! ⇒ Object
- #requires_shipping? ⇒ Boolean
- #shipped? ⇒ Boolean
- #soonest_delivery_date ⇒ Object
- #state_machine ⇒ Object
- #status_css_class ⇒ Object
- #status_progress ⇒ Object
- #tax_amount ⇒ Object
- #tax_amount_by_rates ⇒ Object
- #to_be_paid ⇒ Object
-
#to_be_paid_round ⇒ Object
Mandatory rounding to 0.05 for cash payments in a store.
- #to_be_paid_rounding_difference ⇒ Object
-
#total ⇒ Object
Total of the order.
- #total_excluding_tax ⇒ Object
- #total_items ⇒ Object
- #total_weight ⇒ Object
- #total_weight_in_ounces ⇒ Object
-
#vat_reverse_charge? ⇒ Boolean
By default this method returns false, but you can override it and add your own logic.
Instance Attribute Details
#password ⇒ Object
Returns the value of attribute password.
12 13 14 |
# File 'app/models/spina/shop/order.rb', line 12 def password @password end |
#validate_delivery ⇒ Object
Returns the value of attribute validate_delivery.
12 13 14 |
# File 'app/models/spina/shop/order.rb', line 12 def validate_delivery @validate_delivery end |
#validate_details ⇒ Object
Returns the value of attribute validate_details.
12 13 14 |
# File 'app/models/spina/shop/order.rb', line 12 def validate_details @validate_details end |
#validate_payment ⇒ Object
Returns the value of attribute validate_payment.
12 13 14 |
# File 'app/models/spina/shop/order.rb', line 12 def validate_payment @validate_payment end |
#validate_stock ⇒ Object
Returns the value of attribute validate_stock.
12 13 14 |
# File 'app/models/spina/shop/order.rb', line 12 def validate_stock @validate_stock end |
Class Method Details
.transition_name ⇒ Object
92 93 94 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 92 def self.transition_name :order_transitions end |
Instance Method Details
#age ⇒ Object
157 158 159 160 161 162 |
# File 'app/models/spina/shop/order.rb', line 157 def age now = Time.zone.now if date_of_birth now.year - date_of_birth.year - ((now.month > date_of_birth.month || (now.month == date_of_birth.month && now.day >= date_of_birth.day)) ? 0 : 1) end end |
#apply_gift_card! ⇒ Object
168 169 170 171 172 173 |
# File 'app/models/spina/shop/order.rb', line 168 def apply_gift_card! transaction do update_attributes!(gift_card_amount: gift_card_amount) gift_card.update_attributes!(remaining_balance: gift_card.remaining_balance - gift_card_amount) end end |
#assign_address(address, address_type:) ⇒ Object
78 79 80 81 82 |
# File 'app/models/spina/shop/order.rb', line 78 def assign_address(address, address_type:) [:street1, :postal_code, :city, :house_number, :house_number_addition, :country].each do |f| send("#{address_type}_#{f}=", address.send(f)) end end |
#billing_address ⇒ Object
70 71 72 |
# File 'app/models/spina/shop/order.rb', line 70 def billing_address "#{billing_street1} #{billing_house_number}#{billing_house_number_addition}".strip end |
#billing_first_name ⇒ Object
24 25 26 |
# File 'app/models/spina/shop/order/billing.rb', line 24 def billing_first_name first_name end |
#billing_last_name ⇒ Object
28 29 30 |
# File 'app/models/spina/shop/order/billing.rb', line 28 def billing_last_name last_name end |
#billing_name ⇒ Object
125 126 127 128 |
# File 'app/models/spina/shop/order.rb', line 125 def billing_name full_name = "#{first_name} #{last_name}".strip company.present? ? "#{company} (#{full_name})" : full_name end |
#building? ⇒ Boolean
43 44 45 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 43 def building? current_state == 'building' end |
#cancelled? ⇒ Boolean
15 16 17 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 15 def cancelled? cancelled_at.present? end |
#confirmed? ⇒ Boolean
19 20 21 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 19 def confirmed? confirming_at.present? end |
#confirming? ⇒ Boolean
47 48 49 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 47 def confirming? current_state == 'confirming' end |
#delivered? ⇒ Boolean
35 36 37 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 35 def delivered? delivered_at.present? end |
#delivery_address ⇒ Object
74 75 76 |
# File 'app/models/spina/shop/order.rb', line 74 def delivery_address "#{delivery_street1} #{delivery_house_number}#{delivery_house_number_addition}".strip end |
#delivery_options ⇒ Object
84 85 86 |
# File 'app/models/spina/shop/order.rb', line 84 def DeliveryOption.all end |
#delivery_price ⇒ Object
8 9 10 |
# File 'app/models/spina/shop/order/billing.rb', line 8 def delivery_price read_attribute(:delivery_price) || delivery_option.try(:price_for_order, self) || BigDecimal(0) end |
#delivery_tax_modifier ⇒ Object
16 17 18 |
# File 'app/models/spina/shop/order/billing.rb', line 16 def delivery_tax_modifier (delivery_tax_rate + BigDecimal(100)) / BigDecimal(100) end |
#delivery_tax_rate ⇒ Object
12 13 14 |
# File 'app/models/spina/shop/order/billing.rb', line 12 def delivery_tax_rate read_attribute(:delivery_tax_rate) || delivery_option.try(:tax_group).try(:tax_rate_for_order, self) || BigDecimal(0) end |
#duplicate! ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'app/models/spina/shop/order.rb', line 182 def duplicate! # Duplicate order transaction do shopping_cart = Order.create!(attributes.reject{|key, value| key.in? %w(id delivery_price delivery_tax_rate status received_at shipped_at paid_at delivered_at order_prepared_at payment_id payment_url failed_at cancelled_at delivery_tracking_ids picked_up_at order_number confirming_at created_at updated_at)}) shopping_cart.discount = discount shopping_cart.gift_card = gift_card order_items.each do |order_item| OrderItem.create!(order_item.attributes.reject{|key, value| key.in? %w(id created_at updated_at unit_price unit_cost_price discount_amount weight tax_rate order_id)}.merge(order_id: shopping_cart.id)) end update_attributes!(duplicate: shopping_cart) end end |
#empty? ⇒ Boolean
92 93 94 |
# File 'app/models/spina/shop/order.rb', line 92 def empty? order_items.none? end |
#everything_valid? ⇒ Boolean
195 196 197 198 199 200 201 |
# File 'app/models/spina/shop/order.rb', line 195 def everything_valid? self.validate_details = true self.validate_stock = true self.validate_payment = true self.validate_delivery = true valid? end |
#failed? ⇒ Boolean
11 12 13 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 11 def failed? failed_at.present? end |
#gift_card_amount ⇒ Object
20 21 22 |
# File 'app/models/spina/shop/order/billing.rb', line 20 def gift_card_amount read_attribute(:gift_card_amount) || gift_card.try(:amount_for_order, self) || BigDecimal(0) end |
#merge!(order) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'app/models/spina/shop/order.rb', line 142 def merge!(order) raise Error if confirmed? || order.confirmed? transaction do order.order_items.where(orderable: order_items.map(&:orderable)).each do |duplicate| current_order_item = order_items.find_by(orderable: duplicate.orderable) current_order_item.increment(:quantity, duplicate.quantity) current_order_item.save end order.order_items.where(orderable: order_items.map(&:orderable)).destroy_all order.order_items.update_all(order_id: id) end end |
#nothing_owed? ⇒ Boolean
54 55 56 |
# File 'app/models/spina/shop/order/billing.rb', line 54 def nothing_owed? paid? || to_be_paid == BigDecimal(0) end |
#number ⇒ Object
Order number with zeroes
121 122 123 |
# File 'app/models/spina/shop/order.rb', line 121 def number order_number ? order_number.to_s.rjust(8, '0') : nil end |
#of_age? ⇒ Boolean
164 165 166 |
# File 'app/models/spina/shop/order.rb', line 164 def of_age? age >= 18 if age end |
#order_prepared? ⇒ Boolean
27 28 29 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 27 def order_prepared? order_prepared_at.present? end |
#order_total ⇒ Object
4 5 6 |
# File 'app/models/spina/shop/order/billing.rb', line 4 def order_total order_items.inject(BigDecimal(0)) { |t, i| t + i.total } end |
#paid? ⇒ Boolean
23 24 25 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 23 def paid? paid_at.present? end |
#picked_up? ⇒ Boolean
39 40 41 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 39 def picked_up? picked_up_at.present? end |
#prices_include_tax ⇒ Object
If VAT is reverse charged, all prices must be excluding VAT
116 117 118 |
# File 'app/models/spina/shop/order.rb', line 116 def prices_include_tax vat_reverse_charge? ? false : read_attribute(:prices_include_tax) end |
#products ⇒ Object
100 101 102 103 104 105 106 107 108 |
# File 'app/models/spina/shop/order.rb', line 100 def products order_items.map do |order_item| if order_item.is_product_bundle? order_item.orderable.products else order_item.orderable end end.flatten.uniq end |
#received? ⇒ Boolean
7 8 9 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 7 def received? received_at.present? end |
#remove_gift_card! ⇒ Object
175 176 177 178 179 180 |
# File 'app/models/spina/shop/order.rb', line 175 def remove_gift_card! transaction do gift_card.update_attributes!(remaining_balance: gift_card.remaining_balance + gift_card_amount) update_attributes!(gift_card_amount: nil) end end |
#requires_shipping? ⇒ Boolean
96 97 98 |
# File 'app/models/spina/shop/order.rb', line 96 def requires_shipping? delivery_option.try(:requires_shipping) end |
#shipped? ⇒ Boolean
31 32 33 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 31 def shipped? shipped_at.present? end |
#soonest_delivery_date ⇒ Object
88 89 90 |
# File 'app/models/spina/shop/order.rb', line 88 def soonest_delivery_date delivery_option.try(:soonest_delivery_date_for_order, self) end |
#state_machine ⇒ Object
88 89 90 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 88 def state_machine @state_machine ||= OrderStateMachine.new(self, transition_class: OrderTransition, association_name: :order_transitions) end |
#status_css_class ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 67 def status_css_class case current_state when 'preparing' 'primary' when 'paid' 'primary' when 'shipped' 'success' when 'delivered' 'success' when 'picked_up' 'success' when 'failed' 'danger' when 'cancelled' 'danger' else '' end end |
#status_progress ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'app/models/spina/shop/order/state_machine_transitions.rb', line 51 def status_progress if delivered? || picked_up? 100 elsif shipped? 80 elsif order_prepared? 60 elsif paid? 40 elsif received? 20 else 0 end end |
#tax_amount ⇒ Object
58 59 60 |
# File 'app/models/spina/shop/order/billing.rb', line 58 def tax_amount tax_amount_by_rates.inject(BigDecimal.new(0)) { |t, r| t + r[1][:tax_amount] } end |
#tax_amount_by_rates ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'app/models/spina/shop/order/billing.rb', line 62 def tax_amount_by_rates if vat_reverse_charge? rates = {"0": {tax_amount: BigDecimal.new(0), total: BigDecimal.new(0)}} else items = [order_items] items << OpenStruct.new(tax_rate: delivery_tax_rate, tax_modifier: delivery_tax_modifier, total: delivery_price) if delivery_option.present? rates = items.flatten.inject({}) do |h, item| rate = h[item.tax_rate] ||= { tax_amount: BigDecimal(0), total: BigDecimal(0) } if prices_include_tax rate[:total] += (item.total / item.tax_modifier).round(2) rate[:tax_amount] += item.total - (item.total / item.tax_modifier).round(2) else rate[:total] += item.total rate[:tax_amount] += (item.total * (BigDecimal(item.tax_rate) / BigDecimal(100))).round(2) end h end end rates.sort{|x, y| y[0] <=> x[0]}.to_h end |
#to_be_paid ⇒ Object
41 42 43 |
# File 'app/models/spina/shop/order/billing.rb', line 41 def to_be_paid total - gift_card_amount end |
#to_be_paid_round ⇒ Object
Mandatory rounding to 0.05 for cash payments in a store
46 47 48 |
# File 'app/models/spina/shop/order/billing.rb', line 46 def to_be_paid_round (to_be_paid * 2).round(1, :half_up) / 2 end |
#to_be_paid_rounding_difference ⇒ Object
50 51 52 |
# File 'app/models/spina/shop/order/billing.rb', line 50 def to_be_paid_rounding_difference to_be_paid_round - to_be_paid end |
#total ⇒ Object
Total of the order
33 34 35 |
# File 'app/models/spina/shop/order/billing.rb', line 33 def total order_total + delivery_price + (prices_include_tax ? 0 : tax_amount) end |
#total_excluding_tax ⇒ Object
37 38 39 |
# File 'app/models/spina/shop/order/billing.rb', line 37 def total_excluding_tax total - tax_amount end |
#total_items ⇒ Object
130 131 132 |
# File 'app/models/spina/shop/order.rb', line 130 def total_items order_items.sum(:quantity) end |
#total_weight ⇒ Object
134 135 136 |
# File 'app/models/spina/shop/order.rb', line 134 def total_weight order_items.inject(BigDecimal(0)) { |t, i| t + i.total_weight } end |
#total_weight_in_ounces ⇒ Object
138 139 140 |
# File 'app/models/spina/shop/order.rb', line 138 def total_weight_in_ounces Measurement.parse("#{total_weight} gr").convert_to(:oz).quantity end |
#vat_reverse_charge? ⇒ Boolean
By default this method returns false, but you can override it and add your own logic
111 112 113 |
# File 'app/models/spina/shop/order.rb', line 111 def vat_reverse_charge? false end |