Created
May 15, 2013 18:24
-
-
Save jefflunt/5586134 to your computer and use it in GitHub Desktop.
Order model - after
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Order < ActiveRecord::Base | |
# This array includes the list of possible states that an Order can be in. These reflect the steps | |
# that an order goes through from placement to fulfilment. | |
# | |
# nil The initial state of any Order record | |
# checking_terminals Checking if the terminals involved in this order are online | |
# terminals_offline One of more of the printers/terminals for this order are offline | |
# charging Attempting to charge the customer's credit card via BrainTree | |
# failed_to_charge BrainTree returned an error | |
# printing The order has been sent to the printers/terminals | |
# complete The order appear to be complete, as far as we can tell | |
# | |
# ALL orders are saved in the database, even the ones that fail. This is for tracking reasons and | |
# to give us a better chance of troubleshooting a problem when an order doesn't reach the :completed | |
# state. ONLY completed orders should be shown on the Company dashboard. Orders in any state OTHER | |
# than completed are for internal troubleshooting. | |
# | |
# With the states noted above, there are three states in which a typical order can end: | |
# 1. terminals_offline | |
# 2. failed_to_charge | |
# 3. complete | |
# | |
# If an order ends in any OTHER state than one of these three, then that means something is wrong. | |
# To say it another way, EVERY order should either result in an error that we catch and store in | |
# the order's `failure_details` field, or the order should complete successfully. It only AFTER a | |
# record lands in one of these three states that we return a response to the user's mobile device | |
# with either a success or failure message. | |
# | |
# Finally, any order in a failure status wihout a `failure_details` value that has more information | |
# also indicates that someting went wrong and the details of the error were not captured. | |
VALID_STATES = [ | |
nil, | |
'checking_terminals', | |
'terminals_offline', | |
'charging', | |
'failed_to_charge', | |
'printing', | |
'complete' | |
] | |
... | |
validates :state, :inclusion => { in: VALID_STATES, message: "state - %{value} - invalid. Must be one of the VALID_STATES." } | |
... | |
scope :complete, where("state = 'complete'") | |
scope :terminals_offline, where("state = 'terminals_offline'") | |
scope :failed_to_charge, where("state = 'failed_to_charge'") | |
... | |
def can_be_placed? | |
return false if order_items.empty? | |
return terminals_involved_including_items.all? {|t| t.online? } | |
end | |
def complete? | |
self.state == "complete" | |
end | |
def process_transaction | |
self.update_attribute(:state, 'checking_terminals') | |
unless can_be_placed? | |
self.update_attribute(:state, 'terminals_offline') | |
self.update_attribute(:failure_details, "One or more terminals for this order are offline. DETAILS: #{terminals_involved_including_items.inspect}") | |
self.errors[:base] << 'Unable to place order. Please try again later.' | |
return false | |
end | |
begin | |
self.update_attribute(:state, 'charging') | |
rescue Braintree::AuthenticationError => e | |
self.update_attributes({state: 'failed to charge', failure_details: 'Your Braintree keys failed to authenticate. Check your Braintree initializer file.'}) | |
return false | |
rescue Exception => e | |
self.update_attributes({state: 'failed to charge', failure_details: "Unhandled exception: #{e.inspect}"}) | |
return false | |
end | |
sale_hash = { | |
amount: format_total, | |
payment_method_token: credit_card.bt_token, | |
options: { | |
submit_for_settlement: true | |
} | |
} | |
Rails.logger.info("Attempting to charge order to BrainTree...") | |
sale_hash[:merchant_account_id] = company.merchant_account_id unless company.merchant_account_id.nil? | |
result = Braintree::Transaction.sale(sale_hash) | |
# Documentation on BrainTree results: | |
# https://www.braintreepayments.com/docs/ruby/transactions/result_handling | |
# https://www.braintreepayments.com/docs/ruby/general/result_objects#params | |
if result.success? | |
self.update_attribute(:state, 'printing') | |
self.update_attribute(:transaction_number, result.transaction.id) | |
send_to_printers | |
self.update_attribute(:state, 'complete') | |
else | |
self.update_attribute(:state, 'failed_to_charge') | |
self.update_attribute(:failure_details, result.message) | |
self.errors[:base] << 'Charging your credit card failed. Please check your card and try again.' | |
return false | |
end | |
end | |
def terminals_involved_including_items | |
Rails.logger.info 'Figuring out which printers to use to print this order...' | |
terminals = self.order_items.collect {|oi| oi.menu_item.terminal}.uniq | |
terminals.each do |t| | |
t.items = [] | |
self.order_items.each{|oi| t.items << oi if oi.terminal == t} | |
end | |
terminals | |
end | |
def send_to_printers(reprint=false) | |
Rails.logger.info 'Order#send_to_printers...' | |
terminals_involved_including_items.each {|t| post_to_twisted(t.id, reprint) } | |
end | |
def post_to_twisted(terminal_number, reprint=false) | |
Rails.logger.info 'printing receipt to console' | |
Rails.logger.info 'Posting json to twisted...' | |
::RestClient.post(TWISTED_DOMAIN_ADDRESS, { 'id' => terminal_number.to_s, 'order' => print_receipt(reprint) }) | |
end | |
... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment