quickbooks 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +18 -28
- data/Rakefile +17 -30
- data/doc/classes/{QuickBooks/Models/DataExt.html → Class.html} +151 -140
- data/doc/classes/Class.src/M000003.html +18 -0
- data/doc/classes/Hash.html +164 -0
- data/doc/classes/Hash.src/M000001.html +20 -0
- data/doc/classes/Hash.src/M000002.html +23 -0
- data/doc/classes/{QuickBooks/Models/Transaction.html → Object.html} +207 -201
- data/doc/classes/Object.src/M000004.html +24 -0
- data/doc/classes/Object.src/M000005.html +18 -0
- data/doc/classes/Object.src/M000006.html +19 -0
- data/doc/classes/Object.src/M000007.html +18 -0
- data/doc/classes/{QuickBooks.html → QBHelpers.html} +118 -119
- data/doc/classes/QBHelpers/Ole.html +209 -0
- data/doc/classes/QBHelpers/Ole.src/M000066.html +21 -0
- data/doc/classes/QBHelpers/Ole.src/M000067.html +22 -0
- data/doc/classes/QBHelpers/Ole.src/M000068.html +18 -0
- data/doc/classes/Quickbooks.html +136 -0
- data/doc/classes/Quickbooks/Base.html +618 -0
- data/doc/classes/Quickbooks/Base.src/M000034.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000035.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000036.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000037.html +19 -0
- data/doc/classes/Quickbooks/Base.src/M000038.html +19 -0
- data/doc/classes/Quickbooks/Base.src/M000039.html +25 -0
- data/doc/classes/Quickbooks/Base.src/M000040.html +27 -0
- data/doc/classes/Quickbooks/Base.src/M000041.html +22 -0
- data/doc/classes/Quickbooks/Base.src/M000042.html +30 -0
- data/doc/classes/Quickbooks/Base.src/M000043.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000044.html +19 -0
- data/doc/classes/Quickbooks/Base.src/M000045.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000046.html +19 -0
- data/doc/classes/Quickbooks/Base.src/M000047.html +22 -0
- data/doc/classes/Quickbooks/Base.src/M000048.html +23 -0
- data/doc/classes/Quickbooks/Base.src/M000049.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000050.html +21 -0
- data/doc/classes/Quickbooks/Base.src/M000051.html +25 -0
- data/doc/classes/Quickbooks/Base.src/M000052.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000053.html +36 -0
- data/doc/classes/Quickbooks/Base.src/M000054.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000055.html +18 -0
- data/doc/classes/Quickbooks/Connection.html +369 -0
- data/doc/classes/{QuickBooks/Models/Customer.src/M000002.html → Quickbooks/Connection.src/M000056.html} +17 -17
- data/doc/classes/Quickbooks/Connection.src/M000057.html +19 -0
- data/doc/classes/Quickbooks/Connection.src/M000058.html +25 -0
- data/doc/classes/{QuickBooks/Connection.src/M000018.html → Quickbooks/Connection.src/M000059.html} +17 -17
- data/doc/classes/Quickbooks/Connection.src/M000060.html +18 -0
- data/doc/classes/Quickbooks/Connection.src/M000061.html +21 -0
- data/doc/classes/Quickbooks/Connection.src/M000062.html +24 -0
- data/doc/classes/{QuickBooks/Connection.src/M000016.html → Quickbooks/Connection.src/M000063.html} +19 -20
- data/doc/classes/{QuickBooks/Connection.src/M000019.html → Quickbooks/Connection.src/M000064.html} +23 -21
- data/doc/classes/Quickbooks/Connection.src/M000065.html +24 -0
- data/doc/classes/{QuickBooks/Models.html → Quickbooks/Customer.html} +112 -120
- data/doc/classes/{QuickBooks/Models/CreditCardInfo.html → Quickbooks/ListItem.html} +176 -148
- data/doc/classes/Quickbooks/ListItem.src/M000033.html +31 -0
- data/doc/classes/Quickbooks/Qbxml.html +138 -0
- data/doc/classes/{QuickBooks/Models/ListItem.html → Quickbooks/Qbxml/Error.html} +167 -173
- data/doc/classes/{QuickBooks/Models/Base.src/M000011.html → Quickbooks/Qbxml/Error.src/M000031.html} +17 -17
- data/doc/classes/Quickbooks/Qbxml/Request.html +182 -0
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000024.html +23 -0
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000025.html +19 -0
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000026.html +57 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.html +193 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/M000027.html +22 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/M000028.html +26 -0
- data/doc/classes/{QuickBooks/Models/Base.src/M000014.html → Quickbooks/Qbxml/RequestSet.src/M000029.html} +17 -16
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/M000030.html +22 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSetArrayExt.html +105 -0
- data/doc/classes/{QuickBooks/Connection.html → Quickbooks/Qbxml/Response.html} +301 -278
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000015.html +24 -0
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000016.html +19 -0
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000017.html +45 -0
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000018.html +18 -0
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000019.html +18 -0
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000020.html +18 -0
- data/doc/classes/{QuickBooks/Models/Base.src/M000013.html → Quickbooks/Qbxml/Response.src/M000021.html} +17 -16
- data/doc/classes/{QuickBooks/Models/ListItem.src/M000009.html → Quickbooks/Qbxml/Response.src/M000022.html} +17 -16
- data/doc/classes/Quickbooks/Qbxml/Response.src/M000023.html +52 -0
- data/doc/classes/{QuickBooks/Models/Base.html → Quickbooks/Qbxml/ResponseSet.html} +237 -213
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000008.html +22 -0
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000009.html +26 -0
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000010.html +24 -0
- data/doc/classes/{QuickBooks/Models/Base.src/M000012.html → Quickbooks/Qbxml/ResponseSet.src/M000011.html} +17 -17
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000012.html +27 -0
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000013.html +18 -0
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/M000014.html +18 -0
- data/doc/classes/Quickbooks/Qbxml/ResponseSetArrayExt.html +105 -0
- data/doc/classes/{QuickBooks/Models/Address.html → Quickbooks/Transaction.html} +194 -158
- data/doc/classes/Quickbooks/Transaction.src/M000032.html +26 -0
- data/doc/created.rid +1 -1
- data/doc/files/LICENSE.html +128 -128
- data/doc/files/README.html +185 -173
- data/doc/files/lib/quickbooks/base_rb.html +317 -0
- data/doc/files/lib/quickbooks/connection_rb.html +108 -108
- data/doc/files/lib/quickbooks/models/{base_rb.html → customer_rb.html} +100 -100
- data/doc/files/lib/quickbooks/models/list_item_rb.html +101 -0
- data/doc/files/lib/quickbooks/models/transaction_rb.html +101 -0
- data/doc/files/lib/quickbooks/ole_helper_rb.html +109 -0
- data/doc/files/lib/quickbooks/qbxml/error_rb.html +101 -0
- data/doc/files/lib/quickbooks/{models/models_rb.html → qbxml/request_rb.html} +108 -107
- data/doc/files/lib/quickbooks/qbxml/response_rb.html +109 -0
- data/doc/files/lib/quickbooks/ruby_magic_rb.html +111 -0
- data/doc/files/lib/quickbooks_rb.html +112 -108
- data/doc/fr_class_index.html +44 -35
- data/doc/fr_file_index.html +38 -31
- data/doc/fr_method_index.html +93 -44
- data/doc/index.html +23 -23
- data/doc/rdoc-style.css +207 -207
- data/lib/quickbooks.rb +6 -1
- data/lib/quickbooks/base.rb +282 -0
- data/lib/quickbooks/connection.rb +91 -57
- data/lib/quickbooks/models/customer.rb +71 -0
- data/lib/quickbooks/models/list_item.rb +22 -0
- data/lib/quickbooks/models/transaction.rb +40 -0
- data/lib/quickbooks/ole_helper.rb +47 -0
- data/lib/quickbooks/qbxml/error.rb +20 -0
- data/lib/quickbooks/qbxml/request.rb +120 -0
- data/lib/quickbooks/qbxml/response.rb +176 -0
- data/lib/quickbooks/ruby_magic.rb +67 -0
- metadata +173 -84
- data/doc/classes/QuickBooks/Connection.src/M000015.html +0 -25
- data/doc/classes/QuickBooks/Connection.src/M000017.html +0 -20
- data/doc/classes/QuickBooks/Models/Base.src/M000010.html +0 -19
- data/doc/classes/QuickBooks/Models/Customer.html +0 -424
- data/doc/classes/QuickBooks/Models/Customer.src/M000001.html +0 -34
- data/doc/classes/QuickBooks/Models/Customer.src/M000003.html +0 -18
- data/doc/classes/QuickBooks/Models/ListItem.src/M000008.html +0 -17
- data/doc/classes/QuickBooks/Models/Transaction.src/M000004.html +0 -17
- data/doc/classes/QuickBooks/Models/Transaction.src/M000005.html +0 -17
- data/doc/classes/QuickBooks/Models/Transaction.src/M000006.html +0 -17
- data/doc/classes/QuickBooks/Models/Transaction.src/M000007.html +0 -17
- data/lib/quickbooks/models/base.rb +0 -72
- data/lib/quickbooks/models/models.rb +0 -43
- data/test/quickbooks/quickbooks_test.rb +0 -34
- data/test/test_helper.rb +0 -4
@@ -0,0 +1,71 @@
|
|
1
|
+
module Quickbooks
|
2
|
+
class Customer < ListItem
|
3
|
+
properties :parent_ref,
|
4
|
+
:sublevel,
|
5
|
+
|
6
|
+
:name,
|
7
|
+
:salutation,
|
8
|
+
:first_name,
|
9
|
+
:middle_name,
|
10
|
+
:last_name,
|
11
|
+
:suffix,
|
12
|
+
:company_name,
|
13
|
+
|
14
|
+
:phone,
|
15
|
+
:mobile,
|
16
|
+
:alt_phone,
|
17
|
+
:pager,
|
18
|
+
:fax,
|
19
|
+
:email,
|
20
|
+
:contact,
|
21
|
+
:alt_contact,
|
22
|
+
:bill_address,
|
23
|
+
:ship_address,
|
24
|
+
|
25
|
+
:notes,
|
26
|
+
|
27
|
+
:account_number,
|
28
|
+
:credit_card_info,
|
29
|
+
:credit_limit,
|
30
|
+
:balance,
|
31
|
+
:open_balance,
|
32
|
+
:open_balance_date,
|
33
|
+
:total_balance,
|
34
|
+
:preferred_payment_method_ref,
|
35
|
+
|
36
|
+
:job_status,
|
37
|
+
:job_start_date,
|
38
|
+
:job_projected_end_date,
|
39
|
+
:job_end_date,
|
40
|
+
:job_desc,
|
41
|
+
:job_type_ref,
|
42
|
+
|
43
|
+
:print_as,
|
44
|
+
:customer_type_ref,
|
45
|
+
:delivery_method,
|
46
|
+
:price_level_ref,
|
47
|
+
:terms_ref,
|
48
|
+
:sales_rep_ref,
|
49
|
+
:sales_tax_code_ref,
|
50
|
+
:item_sales_tax_ref,
|
51
|
+
:resale_nmber,
|
52
|
+
:is_statement_with_parent,
|
53
|
+
:data_ext_ref
|
54
|
+
|
55
|
+
# def initialize
|
56
|
+
# @parent_ref = ListItem.new
|
57
|
+
# @bill_address = Address.new
|
58
|
+
# @terms_ref = ListItem.new
|
59
|
+
# @sales_rep_ref = ListItem.new
|
60
|
+
# @sales_tax_code_ref = ListItem.new
|
61
|
+
# @item_sales_tax_ref = ListItem.new
|
62
|
+
# @preferred_payment_method_ref = ListItem.new
|
63
|
+
# @job_type_ref = ListItem.new
|
64
|
+
# @price_live_ref = ListItem.new
|
65
|
+
# @data_ext_ref = ListItem.new
|
66
|
+
# @ship_address = Address.new
|
67
|
+
# @customer_type_ref = ListItem.new
|
68
|
+
# @credit_card_info = CreditCardInfo.new
|
69
|
+
# end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Quickbooks::ListItem < Quickbooks::Base
|
2
|
+
attr_accessor :list_id, :full_name, :edit_sequence, :time_created, :time_modified, :is_active
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def child_types
|
6
|
+
[ "Account", "Account List", "BillingRate",
|
7
|
+
"Class", "Currency", "Customer",
|
8
|
+
"CustomerMessage", "CustomerType",
|
9
|
+
"DateDrivenTerms", "Employee", "ItemDiscount",
|
10
|
+
"ItemFixedAsset", "ItemGroup", "ItemInventory",
|
11
|
+
"ItemInventoryAssembly", "ItemNonInventory",
|
12
|
+
"ItemOtherCharge", "ItemPayment", "ItemSalesTax",
|
13
|
+
"ItemSalesTaxGroup", "ItemService", "ItemSubtotal",
|
14
|
+
"JobType", "OtherName", "PaymentMethod",
|
15
|
+
"PayrollItemNonWage", "PayrollItemWage", "PriceLevel",
|
16
|
+
"SalesRep", "SalesTaxCode", "ShipMethod",
|
17
|
+
"StandardTerms", "TaxCode", "Template", "ToDo",
|
18
|
+
"Vehicle", "Vendor", "VendorType"
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Quickbooks::Transaction < Quickbooks::Base
|
2
|
+
# attr_accessor :id, :ref_number
|
3
|
+
attr_accessor :list_id, :full_name, :edit_sequence, :time_created, :time_modified, :is_active
|
4
|
+
|
5
|
+
# Currently, the following transaction types can be modified:
|
6
|
+
# • Bill
|
7
|
+
# • BillPaymentCheck
|
8
|
+
# • BuildAssembly
|
9
|
+
# • Charge
|
10
|
+
# • Check
|
11
|
+
# • CreditCardCharge
|
12
|
+
# • CreditCardCredit
|
13
|
+
# • CreditMemo
|
14
|
+
# • Deposit
|
15
|
+
# • Estimate
|
16
|
+
# • Invoice
|
17
|
+
# • JournalEntry
|
18
|
+
# • ItemReceipt
|
19
|
+
# • PriceLevel
|
20
|
+
# • PurchaseOrder
|
21
|
+
# • ReceivePayment
|
22
|
+
# • SalesOrder
|
23
|
+
# • SalesReceipt
|
24
|
+
# • StatementCharge
|
25
|
+
# • TimeTracking
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def child_types
|
29
|
+
[ "Bill", "BillPaymentCheck", "BillPaymentCreditCard",
|
30
|
+
"BuildAssembly", "Charge", "Check", "CreditCardCharge",
|
31
|
+
"CreditCardCredit", "CreditCardRefund", "CreditMemo",
|
32
|
+
"Deposit", "Estimate", "InventoryAdjustment",
|
33
|
+
"Invoice", "ItemReceipt", "JournalEntry",
|
34
|
+
"PurchaseOrder", "ReceivePayment", "SalesOrder",
|
35
|
+
"SalesReceipt", "SalesTaxPaymentCheck", "TimeTracking",
|
36
|
+
"VehicleMileage", "VendorCredit"
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# QBHelpers::Ole is a simple helper class that wraps an OLE object and provides methods that make it easier to deal with certain things that OLE makes complicated.
|
2
|
+
|
3
|
+
module QBHelpers
|
4
|
+
class Ole
|
5
|
+
# Simply holds the actual OLE object.
|
6
|
+
attr_reader :ole
|
7
|
+
|
8
|
+
# Pass in the OLE name of the application you want connected to, and the name of a type library, if you need one.
|
9
|
+
def initialize(ole_app, type_library=nil)
|
10
|
+
@ole_app = ole_app
|
11
|
+
@type_library = type_library
|
12
|
+
@ole = WIN32OLE.new(ole_app)
|
13
|
+
self.classes
|
14
|
+
end
|
15
|
+
|
16
|
+
# Finds an OLE variable in the OLE type library, if you specified one in new().
|
17
|
+
# This navigates the OLE classes and constants for you and returns the variable that matches the _var_name_ you specify.
|
18
|
+
# This is used with Quickbooks to get the qbFileOpenDoNotCare parameter to pass to the OpenConnection2 method:
|
19
|
+
# @quickbooks = Ole.new('QBXMLRP2.RequestProcessor', 'QBXMLRP2 1.0 Type Library')
|
20
|
+
# @quickbooks.OpenConnection2('','Sample Application',@quickbooks.get_variable('localQBD'))
|
21
|
+
# @session = @quickbooks.BeginSession('',@quickbooks.get_variable('qbFileOpenDoNotCare'))
|
22
|
+
# ...
|
23
|
+
def get_variable(var_name)
|
24
|
+
return nil unless @type_library
|
25
|
+
self.classes.each do |class_name|
|
26
|
+
found = self.constant_for(class_name.name).variables.find {|var| var.name == var_name}
|
27
|
+
return found if found
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def classes #:nodoc:
|
32
|
+
return nil unless @type_library
|
33
|
+
@classes ||= WIN32OLE_TYPE.ole_classes(@type_library)
|
34
|
+
end
|
35
|
+
|
36
|
+
def constant_for(class_name) #:nodoc:
|
37
|
+
return nil unless @type_library
|
38
|
+
@constant_for ||= {}
|
39
|
+
@constant_for[class_name] ||= WIN32OLE_TYPE.new(@type_library, class_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
# method_missing sends all other methods to the OLE object, so you can treat this object as your OLE object.
|
43
|
+
def method_missing(method_name, *args)
|
44
|
+
@ole.send(method_name, *args)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Quickbooks
|
2
|
+
module Qbxml
|
3
|
+
# This class exists simply to wrap errors in an object similar in structure to a Quickbooks::Base-inherited object, so the error can be extracted, etc.
|
4
|
+
class Error
|
5
|
+
# Stores a log of Quickbooks::Qbxml::Response objects that were a result of methods performed on this object.
|
6
|
+
attr_accessor :response_log
|
7
|
+
def response_log #:nodoc:
|
8
|
+
@response_log || (@response_log = [])
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns success (true/false) status of the last quickbooks communication called from this object.
|
12
|
+
def success?
|
13
|
+
@response_log.last.success?
|
14
|
+
end
|
15
|
+
def inspect #:nodoc:
|
16
|
+
"#<#{self.class.name}:#{self.object_id} #{instance_variables.reject {|i| i.is_one_of?('@response_log', '@original_values')}.map {|i| "#{i}=#{instance_variable_get(i).inspect}"}.join(' ')}>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'quickbooks/ruby_magic'
|
2
|
+
require 'builder'
|
3
|
+
|
4
|
+
module Quickbooks
|
5
|
+
module Qbxml
|
6
|
+
VERSION = '6.0'
|
7
|
+
class RequestSet
|
8
|
+
include Enumerable
|
9
|
+
def set
|
10
|
+
unless @set.is_a?(Array)
|
11
|
+
@set = []
|
12
|
+
@set.extend(Quickbooks::Qbxml::RequestSetArrayExt)
|
13
|
+
end
|
14
|
+
@set
|
15
|
+
end
|
16
|
+
delegate_methods [:each, :length, :first, :last, :[], :map, :join] => :set
|
17
|
+
def <<(qbxml_request)
|
18
|
+
if qbxml_request.is_a?(Quickbooks::Qbxml::Request)
|
19
|
+
set << qbxml_request
|
20
|
+
elsif qbxml_request.respond_to?(:each)
|
21
|
+
qbxml_request.each do |request|
|
22
|
+
self << request
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise ArgumentError, "Cannot add object of type #{qbxml_request.class.name} to a Quickbooks::Qbxml::RequestSet"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(*requests)
|
30
|
+
self << requests
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_xml
|
34
|
+
pre = <<-thequickbooks_qbxmlrequestsetxml
|
35
|
+
<?xml version="1.0" ?>
|
36
|
+
<?qbxml version="#{Quickbooks::Qbxml::VERSION}" ?>
|
37
|
+
<QBXML>
|
38
|
+
<QBXMLMsgsRq onError="stopOnError">
|
39
|
+
thequickbooks_qbxmlrequestsetxml
|
40
|
+
requests = map {|x| x.to_xml(false)}.join
|
41
|
+
post = <<-thequickbooks_qbxmlrequestsetxml
|
42
|
+
</QBXMLMsgsRq>
|
43
|
+
</QBXML>
|
44
|
+
thequickbooks_qbxmlrequestsetxml
|
45
|
+
# puts pre + requests + post
|
46
|
+
pre + requests + post
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Request
|
51
|
+
# @type = there are four types of queries...
|
52
|
+
# 1) List queries (:query)
|
53
|
+
# 2) Object-specific transaction query (:transaction)
|
54
|
+
# 3) Generic transaction query (:any_transaction)
|
55
|
+
# 4) Reports (:report)
|
56
|
+
# ...and then there are Mod requests...
|
57
|
+
# # 1) Mod request (:mod)
|
58
|
+
def initialize(object, type, options={})
|
59
|
+
@type = type
|
60
|
+
raise ArgumentError, "Quickbooks::Qbxml::Requests can only be of one of the following types: :query, :transaction, :any_transaction, :mod, :add, :delete, or :report" unless @type.is_one_of?(:query, :transaction, :any_transaction, :mod, :report, :add, :delete)
|
61
|
+
@object = object
|
62
|
+
@filters = options if @type.is_one_of?(:query, :transaction, :any_transaction, :report)
|
63
|
+
@attributes = options.stringify_keys! if @type.is_one_of?(:mod, :add, :delete)
|
64
|
+
# puts self.inspect
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.next_request_id
|
68
|
+
@request_id ||= 5000
|
69
|
+
@request_id += 1
|
70
|
+
end
|
71
|
+
|
72
|
+
# This is where the magic happens to convert a request object into xml worthy of sending off to quickbooks.
|
73
|
+
def to_xml(as_set=true)
|
74
|
+
return (RequestSet.new(self)).to_xml if as_set # Simple call yields xml as a single request in a request set. However, if the xml for the lone request is required, pass false.
|
75
|
+
req = Builder::XmlMarkup.new(:indent => 2)
|
76
|
+
case
|
77
|
+
when @type.is_one_of?(:query)
|
78
|
+
request_root = "#{@object}QueryRq"
|
79
|
+
container = nil
|
80
|
+
when @type == :mod
|
81
|
+
request_root = "#{@object}ModRq"
|
82
|
+
container = "#{@object}Mod"
|
83
|
+
when @type == :add
|
84
|
+
request_root = "#{@object}AddRq"
|
85
|
+
container = "#{@object}Add"
|
86
|
+
when @type == :delete
|
87
|
+
# request_root = "#{@object}DelRq"
|
88
|
+
request_root = Quickbooks::ListItem.child_types.include?(@object) ? 'ListDelRq' : 'TxnDelRq'
|
89
|
+
container = nil
|
90
|
+
# container = Quickbooks::ListItem.child_types.include?(@object) ? 'ListDelType' : 'TxnDelType'
|
91
|
+
@attributes.merge!((Quickbooks::ListItem.child_types.include?(@object) ? 'ListDelType' : 'TxnDelType') => @object)
|
92
|
+
else
|
93
|
+
raise RuntimeError, "Could not convert this request to qbxml!\n#{self.inspect}"
|
94
|
+
end
|
95
|
+
inner_stuff = lambda {
|
96
|
+
['ListDelType', 'TxnDelType', 'ListID', 'TxnID', 'EditSequence'].each do |key|
|
97
|
+
req.tag!(key, @attributes.delete(key)) if @attributes.has_key?(key)
|
98
|
+
end if @attributes
|
99
|
+
(@filters || @attributes).each do |key,value|
|
100
|
+
req.tag!(key, value)
|
101
|
+
end
|
102
|
+
}
|
103
|
+
req.tag!(request_root, :requestID => self.class.next_request_id) {
|
104
|
+
if container
|
105
|
+
req.tag!(container) {
|
106
|
+
inner_stuff.call
|
107
|
+
}
|
108
|
+
else
|
109
|
+
inner_stuff.call
|
110
|
+
end
|
111
|
+
}
|
112
|
+
# puts req.target!
|
113
|
+
req.target!
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
module RequestSetArrayExt
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'quickbooks/ruby_magic'
|
2
|
+
require 'quickbooks/qbxml/error'
|
3
|
+
|
4
|
+
module Quickbooks
|
5
|
+
module Qbxml
|
6
|
+
class ResponseSet
|
7
|
+
include Enumerable
|
8
|
+
def set
|
9
|
+
unless @set.is_a?(Array)
|
10
|
+
@set = []
|
11
|
+
@set.extend(Quickbooks::Qbxml::ResponseSetArrayExt)
|
12
|
+
end
|
13
|
+
@set
|
14
|
+
end
|
15
|
+
delegate_methods [:each, :length, :first, :last, :[], :map, :join] => :set
|
16
|
+
def <<(qbxml_response)
|
17
|
+
if qbxml_response.is_a?(Quickbooks::Qbxml::Response)
|
18
|
+
set << qbxml_response
|
19
|
+
elsif qbxml_response.respond_to?(:each)
|
20
|
+
qbxml_response.each do |response|
|
21
|
+
self << response
|
22
|
+
end
|
23
|
+
else
|
24
|
+
raise ArgumentError, "Cannot add object of type #{qbxml_response.class.name} to a Quickbooks::Qbxml::ResponseSet"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(xml_or_hash)
|
29
|
+
if(xml_or_hash.is_a?(Hash))
|
30
|
+
self.append_from_hash(xml_or_hash)
|
31
|
+
elsif(xml_or_hash.is_a?(String))
|
32
|
+
self.append_from_xml(xml_or_hash)
|
33
|
+
else
|
34
|
+
raise ArgumentError, "Quickbooks::Qbxml::ResponseSet must be initialized with either a Hash or an xml-formatted String."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def append_from_xml(xml)
|
39
|
+
self.append_from_hash(Hash.from_xml(xml))
|
40
|
+
end
|
41
|
+
def append_from_hash(hsh)
|
42
|
+
to_append = []
|
43
|
+
hsh = hsh['QBXML'] if hsh.has_key?('QBXML')
|
44
|
+
hsh = hsh['QBXMLMsgsRs'] if hsh.has_key?('QBXMLMsgsRs')
|
45
|
+
# responses will contain one or more keys.
|
46
|
+
hsh.each_key do |name|
|
47
|
+
# response_type is either a single response object, or an array of response objects. Force it into an array:
|
48
|
+
responses = hsh[name].is_a?(Array) ? hsh[name] : [hsh[name]]
|
49
|
+
responses.each { |response| to_append << Response.new(name => response) }
|
50
|
+
end
|
51
|
+
self << to_append
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
def from_xml(xml)
|
56
|
+
new.append_from_xml(xml)
|
57
|
+
end
|
58
|
+
def from_hash(hsh)
|
59
|
+
new.append_from_hash(hsh)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Response
|
65
|
+
attr_accessor :response_type, :status, :message, :severity, :ret_items
|
66
|
+
# For Development purposes:
|
67
|
+
attr_accessor :raw_response
|
68
|
+
|
69
|
+
def initialize(xml_or_hash)
|
70
|
+
if(xml_or_hash.is_a?(Hash))
|
71
|
+
self.import_from_hash(xml_or_hash)
|
72
|
+
elsif(xml_or_hash.is_a?(String))
|
73
|
+
self.import_from_xml(xml_or_hash)
|
74
|
+
else
|
75
|
+
raise ArgumentError, "Quickbooks::Qbxml::ResponseSet must be initialized with either a Hash or an xml-formatted String."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def import_from_xml(xml)
|
80
|
+
self.import_from_hash(Hash.from_xml(xml))
|
81
|
+
self
|
82
|
+
end
|
83
|
+
def import_from_hash(hsh)
|
84
|
+
raise ArgumentError, "Hash passed to Quickbooks::Qbxml::Response.from_hash must contain only one top-level key" unless hsh.keys.length == 1
|
85
|
+
name = hsh.keys.first
|
86
|
+
# for development
|
87
|
+
self.raw_response = hsh
|
88
|
+
# * * * *
|
89
|
+
hsh = hsh[name]
|
90
|
+
|
91
|
+
self.status = hsh['statusCode'].to_i
|
92
|
+
self.severity = hsh['statusSeverity']
|
93
|
+
self.message = hsh['statusMessage']
|
94
|
+
# if self.status == 0 # Status is good, proceed with eating the request.
|
95
|
+
if m = name.match(/^(List|Txn)Del(etedQuery)?Rs$/)
|
96
|
+
# (List|Txn)DelRs, or (List|Txn)DeletedQueryRs - both return just a few attributes, like ListID / TxnID and TimeDeleted
|
97
|
+
self.response_type = hsh.delete(m[1]+'DelType')
|
98
|
+
# self.ret_items = ResponseObject.new(self.response_type, hsh.dup)
|
99
|
+
self.ret_items = hsh.dup
|
100
|
+
elsif m = name.match(/^([A-Za-z][a-z]+)(Query|Mod|Add)Rs$/)
|
101
|
+
self.response_type = m[1]
|
102
|
+
# self.ret_items = ResponseObject.new(self.response_type, hsh[self.response_type+'Ret'])
|
103
|
+
self.ret_items = hsh[self.response_type+'Ret']
|
104
|
+
else
|
105
|
+
raise "Could not read this response:\n#{self.raw_response.inspect}"
|
106
|
+
end
|
107
|
+
# else # Status is bad.
|
108
|
+
|
109
|
+
# end
|
110
|
+
# puts self.inspect
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
class << self
|
116
|
+
def from_xml(xml)
|
117
|
+
new.import_from_xml(xml)
|
118
|
+
end
|
119
|
+
def from_hash(hsh)
|
120
|
+
new.import_from_hash(hsh)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def instantiatable? # Just checks to see if it can create an object of this type, and if there is actually data to instantiate
|
125
|
+
self.response_type ? (Quickbooks.const_defined?(self.response_type) && self.ret_items.is_a?(Hash) || (self.ret_items.is_a?(Array) && self.ret_items[0].is_a?(Hash))) : false
|
126
|
+
end
|
127
|
+
def success?
|
128
|
+
self.status == 0
|
129
|
+
end
|
130
|
+
def error?
|
131
|
+
!success?
|
132
|
+
end
|
133
|
+
|
134
|
+
def instantiate(obj=nil)
|
135
|
+
objs = []
|
136
|
+
(self.ret_items.is_a?(Array) ? self.ret_items : [self.ret_items]).each do |ret_item|
|
137
|
+
if instantiatable?
|
138
|
+
if self.status == 0
|
139
|
+
if obj.nil?
|
140
|
+
obj = "Quickbooks::#{self.response_type}".constantize.instantiate(self.ret_items)
|
141
|
+
else
|
142
|
+
obj.class.instantiate(obj, self.ret_items)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
# Instantiatable, but some error status. For any error status
|
146
|
+
if obj.nil? # Must be a new object. Just as well, create a new object WITHOUT any original_attributes.
|
147
|
+
obj = "Quickbooks::#{self.response_type}".constantize.new(self.ret_items)
|
148
|
+
else # An existing object. Must be an update or delete request. Update object's original_attributes.
|
149
|
+
updated = []
|
150
|
+
self.ret_items.each do |k,v|
|
151
|
+
k = k.underscore
|
152
|
+
if obj.original_values[k] != v
|
153
|
+
updated << k
|
154
|
+
obj.original_values[k] = v
|
155
|
+
end
|
156
|
+
end
|
157
|
+
['EditSequence', 'TimeModified', 'TimeCreated'].each do |k|
|
158
|
+
obj.send(k.underscore + '=', self.ret_items[k]) if self.ret_items.has_key?(k) && obj.respond_to?(k.underscore + '=')
|
159
|
+
end
|
160
|
+
self.message = self.message + " Other properties were out of date: [" + updated.join(', ') + '].'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
else
|
164
|
+
obj = Quickbooks::Qbxml::Error.new(self) # If not instantiatable, use this 'Error' object just as a wrapper for the response_log to convey the error response.
|
165
|
+
end
|
166
|
+
obj.response_log << self
|
167
|
+
objs << obj
|
168
|
+
end
|
169
|
+
objs.length > 1 ? objs : objs[0] # Single or nil if not more than one.
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
module ResponseSetArrayExt
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|