quickbooks 0.9.9 → 1.0.2

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.tar.gz.sig CHANGED
Binary file
@@ -9,7 +9,6 @@ lib/quickbooks/adapters/http_adapter.rb
9
9
  lib/quickbooks/adapters/https_adapter.rb
10
10
  lib/quickbooks/adapters/ole_adapter.rb
11
11
  lib/quickbooks/adapters/spew_adapter.rb
12
- lib/quickbooks/adapters/tcp_adapter.rb
13
12
  lib/quickbooks/adapters/test_adapter.rb
14
13
  lib/quickbooks/element.rb
15
14
  lib/quickbooks/element_collection.rb
data/README.txt CHANGED
@@ -9,7 +9,7 @@ The only comprehensive Ruby interface to Quickbooks. THIS IS A DEMO VERSION. Vis
9
9
 
10
10
  == SYNOPSIS:
11
11
 
12
- jim = QB::Customer.first(:fullname => ["Jim Stout"])
12
+ jim = QB::Customer.first(:FullName => "Jim Stout")
13
13
  jim.destroy # Note that you cannot delete items in QuickBooks
14
14
  # but you CAN delete them using the API.
15
15
 
@@ -18,18 +18,18 @@ module Quickbooks
18
18
  class Connection < HttpAdapter::Connection
19
19
  private
20
20
  def new_connection
21
- root_ca_file = '/Users/daniel/Projects/qbonline/demoCA/cacert.pem'
21
+ # root_ca_file = File.dirname(__FILE__) + '/cacert.pem'
22
22
  http = Net::HTTP.new(@ip, @port)
23
23
  http.use_ssl = true
24
- if File.exist?(root_ca_file)
25
- http.ca_file = root_ca_file
26
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
27
- # http.verify_depth = 5
28
- http.verify_depth = 5
29
- http.enable_post_connection_check = false #true
30
- else
24
+ # if File.exist?(root_ca_file)
25
+ # http.ca_file = root_ca_file
26
+ # http.verify_mode = OpenSSL::SSL::VERIFY_PEER
27
+ # # http.verify_depth = 5
28
+ # http.verify_depth = 5
29
+ # http.enable_post_connection_check = false #true
30
+ # else
31
31
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
- end
32
+ # end
33
33
  http
34
34
  end
35
35
  end
@@ -59,7 +59,6 @@ class ElementCollection
59
59
  # TODO: Has a problem when an element is a new_record and a child isn't, or vice-versa.
60
60
  def to_element #:nodoc:
61
61
  element_klass = @type < Quickbooks::Model ? (@type.short_name + (@parent.new_record? ? 'Add' : 'Mod')) : @type.short_name
62
- puts "Converting to #{element_klass}"
63
62
  elements = ElementCollection.new(@parent, element_klass)
64
63
  items.each {|e| elements << (@type < Quickbooks::Model ? e.to_element : e)}
65
64
  return elements
@@ -89,7 +88,11 @@ class ElementCollection
89
88
 
90
89
  def add_item(item)
91
90
  item = @type.new(item) unless item.is_a?(@type)
92
- item.send(:dirty!) if dirty?
91
+ if dirty?
92
+ item.send(:dirty!)
93
+ elsif item.dirty?
94
+ dirty!
95
+ end
93
96
  items << item
94
97
  return item
95
98
  end
@@ -101,5 +104,7 @@ class ElementCollection
101
104
 
102
105
  def dirty!
103
106
  @dirty = true
107
+ # Shall all items be declared dirty when the collection container becomes dirty?
108
+ # items.each {|e| e.send(:dirty!)}
104
109
  end
105
110
  end
@@ -308,9 +308,14 @@ module Quickbooks
308
308
  attributes[key] = ElementCollection.new(self, key, value)
309
309
  attributes[key].send(:dirty!)
310
310
  else
311
- # If it *should* be an array element, it shouldn't be set here as a single value. This is just for safeguard, so that syntax
312
- # always shows what is going on. For an array element, set it with: object.some_attr = [value]
313
- raise RuntimeError, "You can't set a single value into a multi-value element to using equals(=). Use \"model[:#{key}] << value\" to append, or wrap the value in an array -- \"model[:#{key}] = [ value ]\" -- if you want to completely replace the current value set."
311
+ if attributes[key].nil? || attributes[key].empty?
312
+ attributes[key] = ElementCollection.new(self, key, [value])
313
+ attributes[key].send(:dirty!)
314
+ else
315
+ # If it *should* be an array element, it shouldn't be set here as a single value. This is just for safeguard, so that syntax
316
+ # always shows what is going on. For an array element, set it with: object.some_attr = [value]
317
+ raise RuntimeError, "You can't set a singular value directly over an element that already contains multiple values. Use \"model[:#{key}] << value\" to append, or wrap the value in an array to explicitly replace the current contents -- \"model[:#{key}] = [ value ]\"."
318
+ end
314
319
  end
315
320
  else
316
321
  value = @new_record.nil? ? attr_klass.instantiate(value) : attr_klass.new(value) unless value.is_a?(attr_klass)
@@ -518,8 +523,14 @@ module Quickbooks
518
523
 
519
524
  def associate(association_name, value)
520
525
  instance_variable_set("@#{association_name}", value)
521
- ref = value.to_ref
522
526
  ref_klass = self.class.associations[association_name].klass
527
+ ref = if value.respond_to?(:to_ref)
528
+ value.to_ref
529
+ elsif value.respond_to?(:[]) && !value.is_a?(Array)
530
+ ref_klass.new(value)
531
+ else
532
+ raise ArgumentError, "To assign to #{association_name}, set to a #{ref_klass} object or a Hash with the appropriate values to create one."
533
+ end
523
534
  !ref.nil? ?
524
535
  self[ref_klass] = ref :
525
536
  self.delete(ref_klass)
@@ -57,11 +57,11 @@ class String
57
57
  def xml_escaped
58
58
  gsub(/[&<>'"]/) {|match|
59
59
  case match
60
- when '&' then return '&amp;'
61
- when '<' then return '&lt;'
62
- when '>' then return '&gt;'
63
- when "'" then return '&apos;'
64
- when '"' then return '&quote;'
60
+ when '&' then '&amp;'
61
+ when '<' then '&lt;'
62
+ when '>' then '&gt;'
63
+ when "'" then '&apos;'
64
+ when '"' then '&quote;'
65
65
  end
66
66
  }
67
67
  end
@@ -154,6 +154,7 @@ module Quickbooks
154
154
  end
155
155
  end
156
156
  obj = stack.pop
157
+ raise RuntimeError, "Error while parsing xml response. XML:\n#{xml}" if obj.nil?
157
158
  obj.send(:clean!)
158
159
  obj
159
160
  end
@@ -1,9 +1,9 @@
1
1
  module Quickbooks #:nodoc:
2
2
  module VERSION #:nodoc:
3
- MAJOR = 0
4
- MINOR = 9
5
- TINY = 9
6
- BUILD_DATE = '2009-08-05'
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 2
6
+ BUILD_DATE = '2010-01-13'
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
9
9
  end
@@ -35,7 +35,15 @@ module Quickbooks
35
35
  def validate(object,required=true)
36
36
  # Validate the object's contents
37
37
  puts "#{$DEBUG<<"\t"}Validating CONFORMS TO #ComplexType #{name} (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
38
- r = items.inject(Valean.new) {|r,i| r << i.validate(object,required?(i)); r}
38
+ # If the object's contents are Enumerable (multiple values), we'll have to validate each of them individually
39
+ # and return the combined result of all of their validations.
40
+ r = if object.is_a?(Enumerable) && !object.is_a?(Hash)
41
+ object.inject(Valean.new) do |r,obj|
42
+ items.inject(r) {|r,i| r << i.validate(obj,required?(i)); r}
43
+ end
44
+ else
45
+ items.inject(Valean.new) {|r,i| r << i.validate(object,required?(i)); r}
46
+ end
39
47
  $DEBUG.chop! if $DEBUG
40
48
  puts "#{$DEBUG}\t- #{r}" if $DEBUG
41
49
  r
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickbooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.9
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - BehindLogic
@@ -67,7 +67,6 @@ files:
67
67
  - lib/quickbooks/adapters/https_adapter.rb
68
68
  - lib/quickbooks/adapters/ole_adapter.rb
69
69
  - lib/quickbooks/adapters/spew_adapter.rb
70
- - lib/quickbooks/adapters/tcp_adapter.rb
71
70
  - lib/quickbooks/adapters/test_adapter.rb
72
71
  - lib/quickbooks/element.rb
73
72
  - lib/quickbooks/element_collection.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,71 +0,0 @@
1
- require 'net/http'
2
-
3
- # THIS IS A LEGACY ADAPTER, ITS USE IS NOT RECOMMENDED! It is insecure and unstable.
4
- # This adapter sends QBXML via an HTTP connection which is kept open for each session, and expects intelligent real-time QB responses from the other end.
5
- module Quickbooks
6
- module Adapters
7
- module HttpAdapter
8
- # Whatever we do here, we just have to be sure that decrypt(encrypt(data)) == data
9
- module SimpleEncryption
10
- def encrypt(data)
11
- data
12
- end
13
-
14
- def decrypt(data)
15
- data
16
- end
17
- end
18
-
19
- class Connection
20
- include SimpleEncryption
21
- def initialize(ip, port, shared_key)
22
- @ip = ip
23
- @port = port
24
- @shared_key = shared_key
25
- end
26
-
27
- # Returns true if there is an open connection to Quickbooks, false if not. Use session? to determine an open session.
28
- def connected?
29
- (@connection ||= new_connection).started?
30
- end
31
-
32
- def close
33
- @connection.finish rescue nil
34
- end
35
-
36
- # Sends a request to Quickbooks. This request should be a valid QBXML request. Use Qbxml::Request to generate valid requests.
37
- def send_xml(xml)
38
- # TODO: request.basic_auth url.user, url.password
39
- res = try_retry(1, EOFError, :before_retry => lambda {@connection.finish}) {
40
- connection.post('/ProcessRequest', encrypt(xml), {'Content-Type' => 'application/xml'})
41
- }
42
- response = decrypt(res.body)
43
- return response
44
- # rescue => e
45
- # Rescue from the error: I guess we have to return a pretend response that says the network failed.
46
- # raise "Failsafe not yet implemented!: #{e.inspect}"
47
- end
48
-
49
- def qbxml_versions
50
- res = try_retry(1, EOFError, :before_retry => lambda {@connection.finish}) { connection.get('/QBXMLVersionsForSession') }
51
- response = decrypt(res.body)
52
- return response.chomp.split(/,/)
53
- end
54
- def latest_qbxml_version
55
- @latest_qbxml_version ||= qbxml_versions.sort.last
56
- end
57
-
58
- # Returns the active connection to Quickbooks, or creates a new one if none exists.
59
- def connection
60
- @connection.start unless connected?
61
- @connection
62
- end
63
-
64
- private
65
- def new_connection
66
- Net::HTTP.new(@ip, @port)
67
- end
68
- end
69
- end
70
- end
71
- end