Class: Effective::QbRequest
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Effective::QbRequest
- Defined in:
- app/models/effective/qb_request.rb
Constant Summary collapse
- COMPLETED_STATES =
these are the states that signal a request is finished
['Finished', 'Error']
- PROCESSING_STATES =
['Processing', 'CustomerQuery', 'CreateCustomer', 'OrderSync']
Class Method Summary collapse
-
.find_first_response_having_a_request_id(xml) ⇒ Object
searches the XML and returns the first element having a requestID attribute.
-
.find_using_response_qbxml(xml) ⇒ Object
Finds a QbRequest using response qb_xml.
-
.new_requests_for_unsynced_items ⇒ Object
creates (does not persist) QbRequests for outstanding orders.
Instance Method Summary collapse
-
#consume_response_xml(xml) ⇒ Object
parses the response XML and processes it.
-
#generate_request_xml ⇒ Object
generates the actual request XML that will be wrapped in a qbxml_request.
-
#handle_create_customer_response_xml(xml) ⇒ Object
This should be private too, but test needs it.
-
#handle_response_xml(xml) ⇒ Object
handle response xml.
- #has_more_work? ⇒ Boolean
- #state ⇒ Object
-
#to_qb_xml ⇒ Object
outputs this request in qb_xml_format.
-
#transition_state(state) ⇒ Object
transitions the request state and also outputs a log statement.
- #transition_to_finished ⇒ Object
Class Method Details
.find_first_response_having_a_request_id(xml) ⇒ Object
searches the XML and returns the first element having a requestID attribute. Since the application does not bundle requests (yet), this should work.
58 59 60 61 |
# File 'app/models/effective/qb_request.rb', line 58 def self.find_first_response_having_a_request_id(xml) doc = Nokogiri::XML(xml) doc.xpath('//*[@requestID]')[0] end |
.find_using_response_qbxml(xml) ⇒ Object
Finds a QbRequest using response qb_xml. If the response could not be parsed, or if there was no corresponding record, nil will be returned.
41 42 43 44 45 46 |
# File 'app/models/effective/qb_request.rb', line 41 def self.find_using_response_qbxml(xml) return nil if xml.blank? element = Effective::QbRequest.find_first_response_having_a_request_id(xml) Effective::QbRequest.find_by_id(element.attr('requestID').to_i) if element end |
.new_requests_for_unsynced_items ⇒ Object
creates (does not persist) QbRequests for outstanding orders. The caller may choose to persist a request when that request starts communicating with QuickBooks
33 34 35 36 37 |
# File 'app/models/effective/qb_request.rb', line 33 def self.new_requests_for_unsynced_items finished_order_ids = Effective::QbRequest.where(state: 'Finished').pluck(:order_id) Effective::Order.purchased.includes(order_items: [:purchasable, :qb_order_item]) .where.not(id: finished_order_ids).map { |order| Effective::QbRequest.new(order: order) } end |
Instance Method Details
#consume_response_xml(xml) ⇒ Object
parses the response XML and processes it. returns true if the responseXML indicates success, false otherwise
65 66 67 68 |
# File 'app/models/effective/qb_request.rb', line 65 def consume_response_xml(xml) update_attributes!(response_qbxml: xml) handle_response_xml(xml) end |
#generate_request_xml ⇒ Object
generates the actual request XML that will be wrapped in a qbxml_request
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/models/effective/qb_request.rb', line 96 def generate_request_xml # safety checks to make sure we are linked in to the order raise 'Missing Order' unless order if order.order_items.any? { |order_item| order_item.qb_item_name.blank? } raise 'expected .qb_item_name() to be present on Effective::OrderItem' end case self.state when 'CustomerQuery' generate_customer_query_request_xml when 'OrderSync' generate_order_sync_request_xml when 'CreateCustomer' generate_create_customer_request_xml else raise "Unsupported state for generating request XML: #{state}" end end |
#handle_create_customer_response_xml(xml) ⇒ Object
This should be private too, but test needs it
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'app/models/effective/qb_request.rb', line 134 def handle_create_customer_response_xml(xml) queryResponse = Nokogiri::XML(xml).xpath('//CustomerAddRs').first['statusCode'] statusMessage = Nokogiri::XML(xml).xpath('//CustomerAddRs').first['statusMessage'] if '0' == queryResponse # the customer was created log "Customer #{order.billing_name} created successfully" transition_state 'OrderSync' else raise "[Order ##{order.id}] Customer #{order.billing_name} could not be created in QuickBooks: #{statusMessage}" end true # indicate success end |
#handle_response_xml(xml) ⇒ Object
handle response xml
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'app/models/effective/qb_request.rb', line 71 def handle_response_xml(xml) case state when 'CustomerQuery' handle_customer_query_response_xml(xml) when 'CreateCustomer' handle_create_customer_response_xml(xml) when 'OrderSync' handle_order_sync_response_xml(xml) else raise "Request in state #{state} was not expecting a response from the server" end end |
#has_more_work? ⇒ Boolean
48 49 50 |
# File 'app/models/effective/qb_request.rb', line 48 def has_more_work? PROCESSING_STATES.include?(state) end |
#state ⇒ Object
52 53 54 |
# File 'app/models/effective/qb_request.rb', line 52 def state self[:state] || 'Processing' end |
#to_qb_xml ⇒ Object
outputs this request in qb_xml_format
85 86 87 88 89 90 91 92 93 |
# File 'app/models/effective/qb_request.rb', line 85 def to_qb_xml if state == 'Processing' # this is a dummy state -- we need to transition to the CustomerQuery state before any XML goes out. transition_state 'CustomerQuery' end xml = generate_request_xml wrap_qbxml_request(xml) end |
#transition_state(state) ⇒ Object
transitions the request state and also outputs a log statement
117 118 119 120 121 |
# File 'app/models/effective/qb_request.rb', line 117 def transition_state(state) old_state = self.state update_attributes!(state: state) log "Transitioned request state from [#{old_state}] to [#{state}]" end |
#transition_to_finished ⇒ Object
123 124 125 126 127 128 129 130 131 |
# File 'app/models/effective/qb_request.rb', line 123 def transition_to_finished # We create one QbOrderItem for each OrderItem here. order.order_items.each do |order_item| order_item.qb_item_name order_item.qb_order_item.save end transition_state('Finished') end |