quickbooks 0.9.9 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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