quickbooks 0.0.3 → 0.0.5
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 +9 -5
- data/Rakefile +2 -2
- data/doc/classes/Array.html +244 -0
- data/doc/classes/Array.src/M000001.html +18 -0
- data/doc/classes/Array.src/M000002.html +19 -0
- data/doc/classes/Array.src/M000003.html +18 -0
- data/doc/classes/Array.src/M000004.html +23 -0
- data/doc/classes/Array.src/M000005.html +18 -0
- data/doc/classes/Array.src/M000006.html +21 -0
- data/doc/classes/Array.src/M000007.html +18 -0
- data/doc/classes/Array.src/M000008.html +18 -0
- data/doc/classes/Class.html +5 -5
- data/doc/classes/Class.src/{M000003.html → M000027.html} +1 -1
- data/doc/classes/Hash.html +264 -14
- data/doc/classes/Hash.src/M000009.html +18 -0
- data/doc/classes/Hash.src/M000010.html +21 -0
- data/doc/classes/Hash.src/M000011.html +18 -0
- data/doc/classes/Hash.src/M000012.html +21 -0
- data/doc/classes/Hash.src/M000013.html +18 -0
- data/doc/classes/Hash.src/{M000001.html → M000014.html} +6 -5
- data/doc/classes/Hash.src/{M000002.html → M000015.html} +6 -2
- data/doc/classes/Hash.src/M000016.html +20 -0
- data/doc/classes/Hash.src/M000017.html +18 -0
- data/doc/classes/Hash.src/M000018.html +20 -0
- data/doc/classes/Hash.src/M000019.html +38 -0
- data/doc/classes/{Quickbooks/Qbxml/Error.src/M000031.html → Hash.src/M000020.html} +5 -5
- data/doc/classes/Hash.src/M000021.html +18 -0
- data/doc/classes/Hash.src/M000022.html +20 -0
- data/doc/classes/Hash.src/M000023.html +18 -0
- data/doc/classes/Hash.src/M000024.html +18 -0
- data/doc/classes/Hash.src/M000025.html +18 -0
- data/doc/classes/Hash.src/M000026.html +22 -0
- data/doc/classes/Object.html +56 -22
- data/doc/classes/Object.src/{M000004.html → M000028.html} +0 -0
- data/doc/classes/Object.src/{M000005.html → M000029.html} +0 -0
- data/doc/classes/Object.src/{M000006.html → M000030.html} +1 -1
- data/doc/classes/Object.src/{M000007.html → M000031.html} +0 -0
- data/doc/classes/Object.src/M000032.html +18 -0
- data/doc/classes/Object.src/M000033.html +18 -0
- data/doc/classes/QBHelpers/Ole.html +17 -17
- data/doc/classes/QBHelpers/Ole.src/{M000066.html → M000108.html} +0 -0
- data/doc/classes/QBHelpers/Ole.src/{M000067.html → M000109.html} +0 -0
- data/doc/classes/QBHelpers/Ole.src/{M000068.html → M000110.html} +0 -0
- data/doc/classes/Quickbooks.html +44 -4
- data/doc/classes/Quickbooks/{Qbxml/Error.html → Address.html} +14 -43
- data/doc/classes/Quickbooks/Address.src/M000107.html +19 -0
- data/doc/classes/Quickbooks/Base.html +118 -243
- data/doc/classes/Quickbooks/Base.src/{M000034.html → M000080.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/{M000035.html → M000081.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/{M000036.html → M000082.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/{M000037.html → M000083.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/M000084.html +23 -0
- data/doc/classes/Quickbooks/Base.src/{M000041.html → M000085.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/{M000042.html → M000086.html} +2 -2
- data/doc/classes/Quickbooks/Base.src/{M000043.html → M000087.html} +3 -2
- data/doc/classes/Quickbooks/Base.src/M000088.html +19 -0
- data/doc/classes/Quickbooks/Base.src/{M000045.html → M000089.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/M000090.html +19 -0
- data/doc/classes/Quickbooks/Base.src/{M000052.html → M000091.html} +1 -1
- data/doc/classes/Quickbooks/Base.src/M000092.html +45 -0
- data/doc/classes/Quickbooks/Base.src/{M000054.html → M000093.html} +2 -2
- data/doc/classes/Quickbooks/Base.src/M000094.html +18 -0
- data/doc/classes/Quickbooks/Base.src/M000095.html +20 -0
- data/doc/classes/Quickbooks/BillAddress.html +113 -0
- data/doc/classes/Quickbooks/Connection.html +68 -68
- data/doc/classes/Quickbooks/Connection.src/{M000056.html → M000097.html} +0 -0
- data/doc/classes/Quickbooks/Connection.src/{M000057.html → M000098.html} +0 -0
- data/doc/classes/Quickbooks/Connection.src/{M000058.html → M000099.html} +0 -1
- data/doc/classes/Quickbooks/Connection.src/{M000059.html → M000100.html} +1 -1
- data/doc/classes/Quickbooks/Connection.src/{M000060.html → M000101.html} +1 -1
- data/doc/classes/Quickbooks/Connection.src/{M000061.html → M000102.html} +2 -2
- data/doc/classes/Quickbooks/Connection.src/{M000062.html → M000103.html} +1 -1
- data/doc/classes/Quickbooks/Connection.src/{M000063.html → M000104.html} +1 -1
- data/doc/classes/Quickbooks/Connection.src/{M000064.html → M000105.html} +1 -1
- data/doc/classes/Quickbooks/Connection.src/{M000065.html → M000106.html} +2 -2
- data/doc/classes/Quickbooks/CreditCardInfo.html +113 -0
- data/doc/classes/Quickbooks/CustomerTypeRef.html +113 -0
- data/doc/classes/Quickbooks/ItemSalesTaxRef.html +113 -0
- data/doc/classes/Quickbooks/JobTypeRef.html +113 -0
- data/doc/classes/Quickbooks/ListItem.html +21 -44
- data/doc/classes/Quickbooks/ListItem.src/M000078.html +19 -0
- data/doc/classes/Quickbooks/ListItem.src/M000079.html +18 -0
- data/doc/classes/Quickbooks/Model.html +469 -0
- data/doc/classes/Quickbooks/Model.src/M000059.html +24 -0
- data/doc/classes/Quickbooks/Model.src/M000060.html +18 -0
- data/doc/classes/Quickbooks/Model.src/M000061.html +18 -0
- data/doc/classes/Quickbooks/Model.src/M000062.html +18 -0
- data/doc/classes/Quickbooks/Model.src/M000063.html +18 -0
- data/doc/classes/Quickbooks/Model.src/M000064.html +18 -0
- data/doc/classes/Quickbooks/Model.src/M000065.html +32 -0
- data/doc/classes/Quickbooks/Model.src/M000066.html +32 -0
- data/doc/classes/Quickbooks/Model.src/M000067.html +18 -0
- data/doc/classes/Quickbooks/{Base.src/M000046.html → Model.src/M000068.html} +2 -3
- data/doc/classes/Quickbooks/{Base.src/M000047.html → Model.src/M000069.html} +4 -4
- data/doc/classes/Quickbooks/{Base.src/M000048.html → Model.src/M000070.html} +2 -2
- data/doc/classes/Quickbooks/{Base.src/M000049.html → Model.src/M000071.html} +2 -2
- data/doc/classes/Quickbooks/{Base.src/M000050.html → Model.src/M000072.html} +3 -3
- data/doc/classes/Quickbooks/{Base.src/M000051.html → Model.src/M000073.html} +6 -5
- data/doc/classes/Quickbooks/Model.src/M000074.html +28 -0
- data/doc/classes/Quickbooks/Model.src/M000075.html +28 -0
- data/doc/classes/Quickbooks/Model.src/M000076.html +21 -0
- data/doc/classes/Quickbooks/Model.src/M000077.html +23 -0
- data/doc/classes/Quickbooks/ParentRef.html +113 -0
- data/doc/classes/Quickbooks/PreferredPaymentMethodRef.html +113 -0
- data/doc/classes/Quickbooks/PriceLevelRef.html +113 -0
- data/doc/classes/Quickbooks/Qbxml.html +0 -5
- data/doc/classes/Quickbooks/Qbxml/Request.html +55 -23
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000050.html +34 -0
- data/doc/classes/Quickbooks/Qbxml/Request.src/{M000025.html → M000051.html} +2 -2
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000052.html +81 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.html +20 -20
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/{M000027.html → M000053.html} +0 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/{M000028.html → M000054.html} +0 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/{M000029.html → M000055.html} +0 -0
- data/doc/classes/Quickbooks/Qbxml/RequestSet.src/{M000030.html → M000056.html} +0 -0
- data/doc/classes/Quickbooks/Qbxml/Response.html +46 -46
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000015.html → M000041.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000016.html → M000042.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000017.html → M000043.html} +1 -2
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000018.html → M000044.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000019.html → M000045.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000020.html → M000046.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000021.html → M000047.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000022.html → M000048.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/Response.src/{M000023.html → M000049.html} +22 -11
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.html +35 -35
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000008.html → M000034.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000009.html → M000035.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000010.html → M000036.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000011.html → M000037.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000012.html → M000038.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000013.html → M000039.html} +1 -1
- data/doc/classes/Quickbooks/Qbxml/ResponseSet.src/{M000014.html → M000040.html} +1 -1
- data/doc/classes/Quickbooks/Ref.html +139 -0
- data/doc/classes/Quickbooks/Ref.src/M000096.html +18 -0
- data/doc/classes/Quickbooks/SalesRepRef.html +113 -0
- data/doc/classes/Quickbooks/SalesTaxCodeRef.html +113 -0
- data/doc/classes/Quickbooks/ShipAddress.html +113 -0
- data/doc/classes/Quickbooks/TermsRef.html +113 -0
- data/doc/classes/Quickbooks/Transaction.html +21 -62
- data/doc/classes/Quickbooks/Transaction.src/M000057.html +19 -0
- data/doc/classes/Quickbooks/Transaction.src/M000058.html +18 -0
- data/doc/created.rid +1 -1
- data/doc/files/README.html +15 -4
- data/doc/files/lib/quickbooks/base_rb.html +15 -8
- data/doc/files/lib/quickbooks/connection_rb.html +1 -1
- data/doc/files/lib/quickbooks/model_rb.html +108 -0
- data/doc/files/lib/quickbooks/{qbxml/error_rb.html → models/common/address_rb.html} +5 -5
- data/doc/files/lib/quickbooks/models/common/all_refs_rb.html +101 -0
- data/doc/files/lib/quickbooks/models/customer/credit_card_info_rb.html +101 -0
- data/doc/files/lib/quickbooks/models/customer_rb.html +10 -1
- data/doc/files/lib/quickbooks/models/list_item_rb.html +1 -1
- data/doc/files/lib/quickbooks/models/transaction_rb.html +1 -1
- data/doc/files/lib/quickbooks/ole_helper_rb.html +1 -1
- data/doc/files/lib/quickbooks/qbxml/request_rb.html +1 -1
- data/doc/files/lib/quickbooks/qbxml/response_rb.html +1 -2
- data/doc/files/lib/quickbooks/qbxml_rb.html +109 -0
- data/doc/files/lib/quickbooks/ruby_magic_rb.html +1 -1
- data/doc/fr_class_index.html +16 -1
- data/doc/fr_file_index.html +5 -1
- data/doc/fr_method_index.html +110 -68
- data/lib/quickbooks/base.rb +54 -95
- data/lib/quickbooks/connection.rb +2 -3
- data/lib/quickbooks/model.rb +176 -0
- data/lib/quickbooks/models/common/address.rb +14 -0
- data/lib/quickbooks/models/common/all_refs.rb +36 -0
- data/lib/quickbooks/models/customer.rb +30 -31
- data/lib/quickbooks/models/customer/credit_card_info.rb +5 -0
- data/lib/quickbooks/models/list_item.rb +27 -16
- data/lib/quickbooks/models/transaction.rb +21 -12
- data/lib/quickbooks/qbxml.rb +2 -0
- data/lib/quickbooks/qbxml/request.rb +80 -31
- data/lib/quickbooks/qbxml/response.rb +21 -12
- data/lib/quickbooks/ruby_magic.rb +130 -4
- metadata +146 -74
- data/doc/classes/Quickbooks/Base.src/M000038.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000039.html +0 -25
- data/doc/classes/Quickbooks/Base.src/M000040.html +0 -27
- data/doc/classes/Quickbooks/Base.src/M000044.html +0 -19
- data/doc/classes/Quickbooks/Base.src/M000053.html +0 -36
- data/doc/classes/Quickbooks/Base.src/M000055.html +0 -18
- data/doc/classes/Quickbooks/ListItem.src/M000033.html +0 -31
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000024.html +0 -23
- data/doc/classes/Quickbooks/Qbxml/Request.src/M000026.html +0 -57
- data/doc/classes/Quickbooks/Transaction.src/M000032.html +0 -26
- data/lib/quickbooks/qbxml/error.rb +0 -20
|
@@ -42,7 +42,6 @@ module Quickbooks
|
|
|
42
42
|
@quickbooks = Ole.new('QBXMLRP2.RequestProcessor', 'QBXMLRP2 1.0 Type Library')
|
|
43
43
|
@connection_type = @quickbooks.get_variable(connection_type)
|
|
44
44
|
@connection_mode = @quickbooks.get_variable('qbFileOpen'+connection_mode)
|
|
45
|
-
connection # Just to make it fail now instead of later if it can't connect properly.
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
# Returns true if there is an open connection to Quickbooks, false if not. Use session? to determine an open session.
|
|
@@ -57,7 +56,7 @@ module Quickbooks
|
|
|
57
56
|
|
|
58
57
|
# Sends a request to Quickbooks. This request should be a valid QBXML request. Use Quickbooks::Qbxml::Request to generate valid requests.
|
|
59
58
|
def send_xml(xml)
|
|
60
|
-
|
|
59
|
+
@quickbooks.ProcessRequest(session, xml)
|
|
61
60
|
rescue => e
|
|
62
61
|
warn "ERROR processing request:\n#{xml}"
|
|
63
62
|
raise # Reraises the original error, only this way we got the xml output
|
|
@@ -95,7 +94,7 @@ module Quickbooks
|
|
|
95
94
|
# Close the connection to Quickbooks. Automatically ends the session, if there is one.
|
|
96
95
|
def close
|
|
97
96
|
end_session
|
|
98
|
-
if connected? && connection.CloseConnection
|
|
97
|
+
if connected? && connection.CloseConnection
|
|
99
98
|
@connected = false
|
|
100
99
|
@connection = nil
|
|
101
100
|
Quickbooks::Connection.connections = Quickbooks::Connection.connections - [self]
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
require 'quickbooks/ruby_magic'
|
|
2
|
+
module Quickbooks
|
|
3
|
+
CAMELIZE_EXCEPTIONS = {'list_id' => 'ListID', 'txn_id' => 'TxnID', 'owner_id' => 'OwnerID'}
|
|
4
|
+
# These were all created from the info in qbxmlops70.xml, found in the docs in the QBSDK package.
|
|
5
|
+
class Model
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
def inherited(klass)
|
|
9
|
+
def klass.valid_filters
|
|
10
|
+
superclass.valid_filters + (@valid_filters ||= [])
|
|
11
|
+
end
|
|
12
|
+
def klass.filter_aliases
|
|
13
|
+
superclass.filter_aliases.merge(@filter_aliases ||= {})
|
|
14
|
+
end
|
|
15
|
+
klass.instance_variable_set('@object_properties', {})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def valid_filters=(v)
|
|
19
|
+
@valid_filters = v.stringify_values!
|
|
20
|
+
end
|
|
21
|
+
def valid_filters
|
|
22
|
+
@valid_filters ||= []
|
|
23
|
+
end
|
|
24
|
+
def filter_aliases=(v)
|
|
25
|
+
@filter_aliases = v.stringify_keys!.stringify_values!
|
|
26
|
+
end
|
|
27
|
+
def filter_aliases
|
|
28
|
+
@filter_aliases ||= {}
|
|
29
|
+
end
|
|
30
|
+
def camelized_valid_filters
|
|
31
|
+
valid_filters.camelize_values(Quickbooks::CAMELIZE_EXCEPTIONS)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Register multiple read/writable properties at once. For example:
|
|
35
|
+
# read_write :first_name, :last_name, :phone, :alt_phone
|
|
36
|
+
# For reference attributes (like parent_ref), use ParentRef - a class constant for that object.
|
|
37
|
+
# _read_write_ will set the property setter and accessor accordingly.
|
|
38
|
+
def read_write(*args)
|
|
39
|
+
if args.blank?
|
|
40
|
+
@read_write || (@read_write = [])
|
|
41
|
+
else
|
|
42
|
+
args.each do |prop|
|
|
43
|
+
if prop.is_a?(Symbol)
|
|
44
|
+
read_write << prop
|
|
45
|
+
attr_accessor prop
|
|
46
|
+
else
|
|
47
|
+
@object_properties[prop.class_leaf_name.underscore.to_sym] = prop
|
|
48
|
+
read_write << prop.class_leaf_name.underscore.to_sym
|
|
49
|
+
class_eval "def #{prop.class_leaf_name.underscore}=(v); @#{prop.class_leaf_name.underscore} = #{prop.name}.new(v); end
|
|
50
|
+
def #{prop.class_leaf_name.underscore}; @#{prop.class_leaf_name.underscore}; end"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Read-only attributes: These are attributes, but not modifiable in Quickbooks
|
|
57
|
+
def read_only(*args)
|
|
58
|
+
if args.blank?
|
|
59
|
+
@read_only || (@read_only = [])
|
|
60
|
+
else
|
|
61
|
+
args.each do |prop|
|
|
62
|
+
if prop.is_a?(Symbol)
|
|
63
|
+
read_only << prop
|
|
64
|
+
attr_accessor prop
|
|
65
|
+
else
|
|
66
|
+
@object_properties[prop.class_leaf_name.underscore.to_sym] = prop
|
|
67
|
+
read_only << prop.class_leaf_name.underscore.to_sym
|
|
68
|
+
class_eval "def #{prop.class_leaf_name.underscore}=(v); @#{prop.class_leaf_name.underscore} = #{prop.name}.new(v); end
|
|
69
|
+
def #{prop.class_leaf_name.underscore}; @#{prop.class_leaf_name.underscore}; end"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def properties
|
|
76
|
+
read_only + read_write
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
self.valid_filters = [:max_returned]
|
|
81
|
+
|
|
82
|
+
# The default for all subclasses is simply to apply the attributes given, and mark the object as a new_record?
|
|
83
|
+
def initialize(args={})
|
|
84
|
+
self.attributes = args
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns a hash that represents all this object's attributes.
|
|
88
|
+
def attributes(include_read_only=false)
|
|
89
|
+
attrs = {}
|
|
90
|
+
(include_read_only ? self.class.read_only + self.class.read_write : self.class.read_write).each do |column|
|
|
91
|
+
attrs[column.to_s] = instance_variable_get('@' + column.to_s)
|
|
92
|
+
end
|
|
93
|
+
attrs
|
|
94
|
+
end
|
|
95
|
+
# Updates all attributes included in _attrs_ to the values given. The object will now be dirty?.
|
|
96
|
+
def attributes=(attrs)
|
|
97
|
+
raise ArgumentError, "attributes can only be set to a hash of attributes" unless attrs.is_a?(Hash)
|
|
98
|
+
attrs.each do |key,value|
|
|
99
|
+
if self.respond_to?(key.to_s.underscore+'=')
|
|
100
|
+
self.send(key.to_s.underscore+'=', value)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Keeps track of the original values the object had when it was instantiated from a quickbooks response. dirty? and dirty_attributes compare the current values with these ones.
|
|
106
|
+
def original_values
|
|
107
|
+
@original_values || (@original_values = {})
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns true if any attributes have changed since the object was last loaded or updated from Quickbooks.
|
|
111
|
+
def dirty?
|
|
112
|
+
# Concept: For each column that the current model includes, has the value been changed?
|
|
113
|
+
self.class.read_write.any? do |column|
|
|
114
|
+
self.instance_variable_get('@' + column.to_s) != original_values[column.to_s]
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Returns a hash of the attributes and their (new) values that have been changed since the object was last loaded or updated from Quickbooks.
|
|
119
|
+
# If you send in some attributes, it will compare to those given instead of original_attributes.
|
|
120
|
+
def dirty_attributes(compare={})
|
|
121
|
+
compare = original_values if compare.blank?
|
|
122
|
+
pairs = {}
|
|
123
|
+
self.class.read_write.each do |column|
|
|
124
|
+
value = instance_variable_get('@' + column.to_s)
|
|
125
|
+
if value != compare[column.to_s]
|
|
126
|
+
pairs[column.to_s] = value
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
pairs
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def to_dirty_hash
|
|
133
|
+
hsh = {}
|
|
134
|
+
self.dirty_attributes.each do |key,value|
|
|
135
|
+
if value.is_a?(Quickbooks::Model)
|
|
136
|
+
h = value.to_dirty_hash
|
|
137
|
+
hsh[key] = h unless h.blank?
|
|
138
|
+
else
|
|
139
|
+
hsh[key] = value
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
hsh.order!(self.class.read_write.stringify_values)
|
|
143
|
+
hsh
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def to_hash(include_read_only=false)
|
|
147
|
+
hsh = {}
|
|
148
|
+
self.attributes(include_read_only).each do |key,value|
|
|
149
|
+
if value.is_a?(Quickbooks::Model)
|
|
150
|
+
h = value.to_hash(include_read_only)
|
|
151
|
+
hsh[key] = h unless h.blank?
|
|
152
|
+
else
|
|
153
|
+
hsh[key] = value
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
hsh.order!((include_read_only ? self.class.read_only + self.class.read_write : self.class.read_write).stringify_values)
|
|
157
|
+
hsh
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def ==(other)
|
|
161
|
+
return false unless other.is_a?(self.class)
|
|
162
|
+
!self.class.read_write.any? do |column|
|
|
163
|
+
self.instance_variable_get('@' + column.to_s) != other.instance_variable_get('@' + column.to_s)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def ===(other)
|
|
168
|
+
# other could be a hash
|
|
169
|
+
if other.is_a?(Hash)
|
|
170
|
+
self == self.class.new(other)
|
|
171
|
+
else
|
|
172
|
+
self == other
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Quickbooks
|
|
2
|
+
class Address < Model
|
|
3
|
+
def self.inherited(klass)
|
|
4
|
+
super
|
|
5
|
+
klass.read_write :addr1, :addr2, :addr3, :addr4, :addr5, :city, :state, :postal_code, :country, :note
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class BillAddress < Address
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class ShipAddress < Address
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Quickbooks
|
|
2
|
+
class Ref < Model
|
|
3
|
+
def self.inherited(klass)
|
|
4
|
+
klass.read_only :list_id, :full_name
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Put in here the connector code for 'association' calls
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class ParentRef < Ref
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class CustomerTypeRef < Ref
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TermsRef < Ref
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class SalesRepRef < Ref
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class SalesTaxCodeRef < Ref
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class ItemSalesTaxRef < Ref
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class PreferredPaymentMethodRef < Ref
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class JobTypeRef < Ref
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class PriceLevelRef < Ref
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,56 +1,55 @@
|
|
|
1
|
+
require 'quickbooks/models/common/all_refs'
|
|
2
|
+
require 'quickbooks/models/common/address'
|
|
3
|
+
require 'quickbooks/models/customer/credit_card_info'
|
|
4
|
+
|
|
1
5
|
module Quickbooks
|
|
2
6
|
class Customer < ListItem
|
|
3
|
-
|
|
4
|
-
:sublevel,
|
|
7
|
+
self.valid_filters = [:active_status, :from_modified_date, :to_modified_date, :name_filter, :name_range_filter, :total_balance_filter]
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
# Properties are in the order required by QBXML
|
|
10
|
+
read_write :name,
|
|
11
|
+
:is_active,
|
|
12
|
+
ParentRef,
|
|
13
|
+
:company_name,
|
|
7
14
|
:salutation,
|
|
8
15
|
:first_name,
|
|
9
16
|
:middle_name,
|
|
10
17
|
:last_name,
|
|
11
18
|
:suffix,
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
BillAddress,
|
|
20
|
+
ShipAddress,
|
|
21
|
+
:print_as,
|
|
14
22
|
:phone,
|
|
15
|
-
:mobile,
|
|
16
|
-
:alt_phone,
|
|
23
|
+
# :mobile, # only in QBOE
|
|
17
24
|
:pager,
|
|
25
|
+
:alt_phone,
|
|
18
26
|
:fax,
|
|
19
27
|
:email,
|
|
20
28
|
:contact,
|
|
21
29
|
:alt_contact,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
:
|
|
26
|
-
|
|
30
|
+
CustomerTypeRef,
|
|
31
|
+
TermsRef,
|
|
32
|
+
SalesRepRef,
|
|
33
|
+
# :open_balance,
|
|
34
|
+
# :open_balance_date,
|
|
35
|
+
SalesTaxCodeRef,
|
|
36
|
+
ItemSalesTaxRef,
|
|
37
|
+
:sales_tax_country,
|
|
38
|
+
:resale_nmber,
|
|
27
39
|
:account_number,
|
|
28
|
-
:credit_card_info,
|
|
29
40
|
:credit_limit,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
:open_balance_date,
|
|
33
|
-
:total_balance,
|
|
34
|
-
:preferred_payment_method_ref,
|
|
35
|
-
|
|
41
|
+
PreferredPaymentMethodRef,
|
|
42
|
+
CreditCardInfo,
|
|
36
43
|
:job_status,
|
|
37
44
|
:job_start_date,
|
|
38
45
|
:job_projected_end_date,
|
|
39
46
|
:job_end_date,
|
|
40
47
|
:job_desc,
|
|
41
|
-
|
|
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,
|
|
48
|
+
JobTypeRef,
|
|
49
|
+
:notes,
|
|
52
50
|
:is_statement_with_parent,
|
|
53
|
-
:
|
|
51
|
+
:delivery_method,
|
|
52
|
+
PriceLevelRef
|
|
54
53
|
|
|
55
54
|
# def initialize
|
|
56
55
|
# @parent_ref = ListItem.new
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
class Quickbooks::ListItem < Quickbooks::Base
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
self.valid_filters = [:list_id, :full_name]
|
|
4
|
+
self.filter_aliases = {:modified_after => :from_modified_date, :modified_before => :to_modified_date}
|
|
5
|
+
|
|
6
|
+
def self.inherited(klass)
|
|
7
|
+
super
|
|
8
|
+
klass.read_only :list_id, :full_name, :edit_sequence, :time_created, :time_modified
|
|
9
|
+
end
|
|
3
10
|
|
|
4
11
|
class << self
|
|
5
|
-
def
|
|
6
|
-
|
|
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
|
-
]
|
|
12
|
+
def ListOrTxn
|
|
13
|
+
'List'
|
|
20
14
|
end
|
|
15
|
+
|
|
16
|
+
# def child_types
|
|
17
|
+
# [ "Account", "Account List", "BillingRate",
|
|
18
|
+
# "Class", "Currency", "Customer",
|
|
19
|
+
# "CustomerMessage", "CustomerType",
|
|
20
|
+
# "DateDrivenTerms", "Employee", "ItemDiscount",
|
|
21
|
+
# "ItemFixedAsset", "ItemGroup", "ItemInventory",
|
|
22
|
+
# "ItemInventoryAssembly", "ItemNonInventory",
|
|
23
|
+
# "ItemOtherCharge", "ItemPayment", "ItemSalesTax",
|
|
24
|
+
# "ItemSalesTaxGroup", "ItemService", "ItemSubtotal",
|
|
25
|
+
# "JobType", "OtherName", "PaymentMethod",
|
|
26
|
+
# "PayrollItemNonWage", "PayrollItemWage", "PriceLevel",
|
|
27
|
+
# "SalesRep", "SalesTaxCode", "ShipMethod",
|
|
28
|
+
# "StandardTerms", "TaxCode", "Template", "ToDo",
|
|
29
|
+
# "Vehicle", "Vendor", "VendorType"
|
|
30
|
+
# ]
|
|
31
|
+
# end
|
|
21
32
|
end
|
|
22
33
|
end
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
class Quickbooks::Transaction < Quickbooks::Base
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
self.valid_filters = [:txn_id]
|
|
4
|
+
|
|
5
|
+
def self.inherited(klass)
|
|
6
|
+
super
|
|
7
|
+
klass.read_only :txn_id, :full_name, :edit_sequence, :time_created, :time_modified
|
|
8
|
+
end
|
|
4
9
|
|
|
5
10
|
# Currently, the following transaction types can be modified:
|
|
6
11
|
# • Bill
|
|
@@ -25,16 +30,20 @@ class Quickbooks::Transaction < Quickbooks::Base
|
|
|
25
30
|
# • TimeTracking
|
|
26
31
|
|
|
27
32
|
class << self
|
|
28
|
-
def
|
|
29
|
-
|
|
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
|
-
]
|
|
33
|
+
def ListOrTxn
|
|
34
|
+
'Txn'
|
|
38
35
|
end
|
|
36
|
+
|
|
37
|
+
# def child_types
|
|
38
|
+
# [ "Bill", "BillPaymentCheck", "BillPaymentCreditCard",
|
|
39
|
+
# "BuildAssembly", "Charge", "Check", "CreditCardCharge",
|
|
40
|
+
# "CreditCardCredit", "CreditCardRefund", "CreditMemo",
|
|
41
|
+
# "Deposit", "Estimate", "InventoryAdjustment",
|
|
42
|
+
# "Invoice", "ItemReceipt", "JournalEntry",
|
|
43
|
+
# "PurchaseOrder", "ReceivePayment", "SalesOrder",
|
|
44
|
+
# "SalesReceipt", "SalesTaxPaymentCheck", "TimeTracking",
|
|
45
|
+
# "VehicleMileage", "VendorCredit"
|
|
46
|
+
# ]
|
|
47
|
+
# end
|
|
39
48
|
end
|
|
40
49
|
end
|
|
@@ -48,57 +48,96 @@ thequickbooks_qbxmlrequestsetxml
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
class Request
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
|
|
51
|
+
# 1. List queries (:query)
|
|
52
|
+
# Request.new(object, :query) # <= will return the record matching the object supplied (automatically searches by list_id or txn_id)
|
|
53
|
+
# Request.new(Customer, :query, :limit => 1) # <= will return the first customer
|
|
54
|
+
# Request.new(Customer, :query, /some match/) # <= will return all customers matching the regexp
|
|
55
|
+
# 2. Object-specific transaction query (:transaction)
|
|
56
|
+
# Request.new(Transaction, :query) # <= will return the transaction matching the object supplied
|
|
57
|
+
# 3. Mod requests (:mod)
|
|
58
|
+
# Request.new(object, :mod) # <= will update the object
|
|
59
|
+
# 4. Delete requests (:delete)
|
|
60
|
+
# Request.new(object, :delete) # <= will delete the object
|
|
61
|
+
# We want the attributes of the object when we are updating, but no other time.
|
|
62
|
+
def initialize(object, type, options_or_regexp={})
|
|
63
|
+
options = options_or_regexp.is_a?(Regexp) ? {:matches => options_or_regexp} : options_or_regexp
|
|
59
64
|
@type = type
|
|
60
65
|
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)
|
|
66
|
+
@klass = object.is_a?(Class) ? object : object.class
|
|
61
67
|
@object = object
|
|
62
|
-
@
|
|
63
|
-
|
|
64
|
-
#
|
|
68
|
+
@options = options
|
|
69
|
+
|
|
70
|
+
# Return only specific properties: Request.new(Customer, :query, :only => [:list_id, :full_name]); Quickbooks::Customer.first(:only => :list_id)
|
|
71
|
+
@ret_elements = @options.delete(:only).to_a.only(@klass.properties).order!(@klass.properties).stringify_values.camelize_values!(Quickbooks::CAMELIZE_EXCEPTIONS) if @options.has_key?(:only)
|
|
72
|
+
|
|
73
|
+
# Includes only valid filters + aliases for valid filters, then transforms aliased filters to real filters, then camelizes keys to prepare for writing to XML, lastly orders the keys to a valid filter order.
|
|
74
|
+
# You may optionally have ListID OR FullName OR ( MaxReturned AND ActiveStatus AND FromModifiedDate AND ToModifiedDate AND ( NameFilter OR NameRangeFilter ) )
|
|
75
|
+
@filters = options.stringify_keys.only(@klass.valid_filters + @klass.filter_aliases.keys).transform_keys!(@klass.filter_aliases).camelize_keys!(Quickbooks::CAMELIZE_EXCEPTIONS).order!(@klass.camelized_valid_filters)
|
|
76
|
+
|
|
77
|
+
# Complain if:
|
|
78
|
+
# 1) type is :mod or :delete, and object supplied is not a valid model
|
|
79
|
+
raise ArgumentError, "A Quickbooks record object must be supplied to perform an add, mod or del action" if @type.is_one_of?(:add, :mod, :delete) && !@object.is_a?(Quickbooks::Base)
|
|
65
80
|
end
|
|
66
81
|
|
|
67
82
|
def self.next_request_id
|
|
68
|
-
@request_id ||=
|
|
83
|
+
@request_id ||= 0
|
|
69
84
|
@request_id += 1
|
|
70
85
|
end
|
|
71
86
|
|
|
72
|
-
# This is where the magic happens to convert a request object into xml worthy of
|
|
87
|
+
# This is where the magic happens to convert a request object into xml worthy of quickbooks.
|
|
73
88
|
def to_xml(as_set=true)
|
|
74
89
|
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
90
|
req = Builder::XmlMarkup.new(:indent => 2)
|
|
76
|
-
case
|
|
91
|
+
request_root, container = case
|
|
77
92
|
when @type.is_one_of?(:query)
|
|
78
|
-
|
|
79
|
-
container = nil
|
|
80
|
-
when @type == :mod
|
|
81
|
-
request_root = "#{@object}ModRq"
|
|
82
|
-
container = "#{@object}Mod"
|
|
93
|
+
["#{@klass.class_leaf_name}QueryRq", nil]
|
|
83
94
|
when @type == :add
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
["#{@klass.class_leaf_name}AddRq", "#{@klass.class_leaf_name}Add"]
|
|
96
|
+
when @type == :mod
|
|
97
|
+
["#{@klass.class_leaf_name}ModRq", "#{@klass.class_leaf_name}Mod"]
|
|
86
98
|
when @type == :delete
|
|
87
|
-
|
|
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)
|
|
99
|
+
["#{@klass.ListOrTxn}DelRq", nil]
|
|
92
100
|
else
|
|
93
101
|
raise RuntimeError, "Could not convert this request to qbxml!\n#{self.inspect}"
|
|
94
102
|
end
|
|
95
103
|
inner_stuff = lambda {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
deep_tag = lambda {|k,v|
|
|
105
|
+
if v.is_a?(Hash)
|
|
106
|
+
if k == ''
|
|
107
|
+
v.each { |k,v|
|
|
108
|
+
deep_tag.call(k,v)
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
req.tag!(k.camelcase) { v.each { |k,v| deep_tag.call(k,v) } }
|
|
112
|
+
end
|
|
113
|
+
else
|
|
114
|
+
req.tag!(k.camelcase,uncast(v))
|
|
115
|
+
end
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Add the specific elements for the respective request type
|
|
119
|
+
if @type.is_one_of?(:add, :mod)
|
|
120
|
+
if @type == :mod
|
|
121
|
+
# First the ObjectId:
|
|
122
|
+
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
123
|
+
# Second the EditSequence
|
|
124
|
+
req.tag!('EditSequence', @object.send(:edit_sequence))
|
|
125
|
+
end
|
|
126
|
+
# Then, all the dirty_attributes
|
|
127
|
+
deep_tag.call('',@object.to_dirty_hash) # (this is an hash statically ordered to the model's qbxml attribute order)
|
|
128
|
+
elsif @type == :query && @object.class == @klass
|
|
129
|
+
# Sent an instance object for a query - we should include the ListId/TxnId (then other filters?)
|
|
130
|
+
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
131
|
+
deep_tag.call('', @filters)
|
|
132
|
+
elsif @type == :delete
|
|
133
|
+
req.tag!(@klass.ListOrTxn + 'DelType', @klass.class_leaf_name)
|
|
134
|
+
req.tag!(@klass.ListOrTxn + 'ID', @object.send("#{@klass.ListOrTxn}Id".underscore))
|
|
135
|
+
else
|
|
136
|
+
# just filters
|
|
137
|
+
deep_tag.call('', @filters)
|
|
101
138
|
end
|
|
139
|
+
# Lastly, specify the fields to return, if desired
|
|
140
|
+
@ret_elements.each { |r| req.tag!('IncludeRetElement', r) } if !@ret_elements.blank?
|
|
102
141
|
}
|
|
103
142
|
req.tag!(request_root, :requestID => self.class.next_request_id) {
|
|
104
143
|
if container
|
|
@@ -112,6 +151,16 @@ thequickbooks_qbxmlrequestsetxml
|
|
|
112
151
|
# puts req.target!
|
|
113
152
|
req.target!
|
|
114
153
|
end
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
def uncast(v)
|
|
157
|
+
case
|
|
158
|
+
when v.is_a?(Time)
|
|
159
|
+
v.xmlschema
|
|
160
|
+
else
|
|
161
|
+
v
|
|
162
|
+
end
|
|
163
|
+
end
|
|
115
164
|
end
|
|
116
165
|
|
|
117
166
|
module RequestSetArrayExt
|