quickeebooks 0.1.6 → 0.1.7

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.
Files changed (33) hide show
  1. data/Gemfile.lock +1 -1
  2. data/HISTORY.md +4 -0
  3. data/README.md +2 -0
  4. data/coverage/index.html +3785 -3233
  5. data/lib/quickeebooks.rb +7 -0
  6. data/lib/quickeebooks/common/online_entity_model.rb +0 -2
  7. data/lib/quickeebooks/online/model/account_detail_type.rb +116 -223
  8. data/lib/quickeebooks/online/model/customer.rb +33 -2
  9. data/lib/quickeebooks/online/model/employee.rb +25 -0
  10. data/lib/quickeebooks/online/model/time_activity.rb +48 -0
  11. data/lib/quickeebooks/online/model/time_activity_employee.rb +12 -0
  12. data/lib/quickeebooks/online/model/time_activity_vendor.rb +12 -0
  13. data/lib/quickeebooks/online/model/vendor.rb +1 -0
  14. data/lib/quickeebooks/online/service/employee.rb +15 -0
  15. data/lib/quickeebooks/online/service/service_base.rb +8 -1
  16. data/lib/quickeebooks/online/service/time_activity.rb +15 -0
  17. data/lib/quickeebooks/version.rb +1 -1
  18. data/spec/quickeebooks/online/customer_spec.rb +1 -1
  19. data/spec/quickeebooks/online/employee_spec.rb +31 -0
  20. data/spec/quickeebooks/online/services/employee_spec.rb +83 -0
  21. data/spec/quickeebooks/online/services/service_base_spec.rb +12 -0
  22. data/spec/quickeebooks/online/services/time_activity_spec.rb +89 -0
  23. data/spec/quickeebooks/online/time_activity_spec.rb +18 -0
  24. data/spec/xml/online/employee.xml +31 -0
  25. data/spec/xml/online/employee2.xml +31 -0
  26. data/spec/xml/online/employees.xml +36 -0
  27. data/spec/xml/online/time_activities.xml +27 -0
  28. data/spec/xml/online/time_activity.xml +21 -0
  29. data/spec/xml/online/time_activity2.xml +21 -0
  30. metadata +18 -5
  31. data/tmp/blocks.rb +0 -14
  32. data/tmp/create_customer_windows.rb +0 -59
  33. data/tmp/online.rb +0 -23
@@ -0,0 +1,48 @@
1
+ require "quickeebooks"
2
+ require "quickeebooks/online/model/id"
3
+ require "quickeebooks/online/model/meta_data"
4
+ require "quickeebooks/online/model/time_activity_employee"
5
+ require "quickeebooks/online/model/time_activity_vendor"
6
+
7
+ module Quickeebooks
8
+ module Online
9
+ module Model
10
+ class TimeActivity < Quickeebooks::Online::Model::IntuitType
11
+ include ActiveModel::Validations
12
+ include OnlineEntityModel
13
+
14
+ XML_NODE = "TimeActivity"
15
+ REST_RESOURCE = "time_activity"
16
+
17
+ xml_accessor :txn_date, :from => 'TxnDate'
18
+ xml_accessor :name_of, :from => 'NameOf'
19
+
20
+ xml_accessor :employee, :from => 'Employee', :as => Quickeebooks::Online::Model::TimeActivityEmployee
21
+ xml_accessor :vendor, :from => 'Vendor', :as => Quickeebooks::Online::Model::TimeActivityVendor
22
+
23
+ xml_accessor :customer_id, :from => 'CustomerId'
24
+ xml_accessor :customer_name, :from => 'CustomerName'
25
+ xml_accessor :item_id, :from => 'ItemId', :as => Quickeebooks::Online::Model::Id
26
+ xml_accessor :class_id, :from => 'ClassId', :as => Quickeebooks::Online::Model::Id
27
+ xml_accessor :billable_status, :from => 'BillableStatus'
28
+ xml_accessor :taxable, :from => 'Taxable'
29
+ xml_accessor :hourly_rate, :from => 'HourlyRate'
30
+ xml_accessor :hours, :from => 'Hours', :as => Integer
31
+ xml_accessor :minutes, :from => 'Minutes', :as => Integer
32
+ xml_accessor :seconds, :from => 'Seconds', :as => Integer
33
+ xml_accessor :break_hours, :from => 'BreakHours', :as => Integer
34
+ xml_accessor :break_minutes, :from => 'BreakMinutes', :as => Integer
35
+ xml_accessor :start_time, :from => 'StartTime', :as => DateTime
36
+ xml_accessor :end_time, :from => 'EndTime', :as => DateTime
37
+ xml_accessor :description, :from => 'Description'
38
+
39
+ validates_presence_of :name_of, :customer_id, :hourly_rate
40
+
41
+
42
+ def self.resource_for_collection
43
+ 'time-activities'
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ require "quickeebooks"
2
+
3
+ module Quickeebooks
4
+ module Online
5
+ module Model
6
+ class TimeActivityEmployee < Quickeebooks::Online::Model::IntuitType
7
+ xml_accessor :employee_id, :from => 'EmployeeId', :as => Quickeebooks::Online::Model::Id
8
+ xml_accessor :employee_name, :from => 'EmployeeName'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require "quickeebooks"
2
+
3
+ module Quickeebooks
4
+ module Online
5
+ module Model
6
+ class TimeActivityVendor < Quickeebooks::Online::Model::IntuitType
7
+ xml_accessor :vendor_id, :from => 'VendorId', :as => Quickeebooks::Online::Model::Id
8
+ xml_accessor :vendor_name, :from => 'VendorName'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -20,6 +20,7 @@ module Quickeebooks
20
20
  REST_RESOURCE = "vendor"
21
21
 
22
22
  xml_accessor :is_1099?, :from => 'Vendor1099'
23
+ validates_length_of :name, :minimum => 1
23
24
 
24
25
  end
25
26
  end
@@ -0,0 +1,15 @@
1
+ require 'quickeebooks/online/service/service_base'
2
+ require 'quickeebooks/online/model/employee'
3
+ require 'quickeebooks/common/service_crud'
4
+ require 'nokogiri'
5
+
6
+ module Quickeebooks
7
+ module Online
8
+ module Service
9
+ class Employee < ServiceBase
10
+ include ServiceCRUD
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -75,6 +75,13 @@ module Quickeebooks
75
75
  Nokogiri::XML(xml)
76
76
  end
77
77
 
78
+ def escape_filter(str)
79
+ # Ampersand needs to double encoded within an Oath request.
80
+ # CGI.escape will take the #26 and properly turn it into #2526
81
+ str.gsub!('&','%26')
82
+ CGI.escape(str)
83
+ end
84
+
78
85
  def valid_xml_document(xml)
79
86
  %Q{<?xml version="1.0" encoding="utf-8"?>\n#{xml.strip}}
80
87
  end
@@ -86,7 +93,7 @@ module Quickeebooks
86
93
 
87
94
  if filters.is_a?(Array) && filters.length > 0
88
95
  filter_string = filters.collect { |f| f.to_s }
89
- post_body_lines << "Filter=#{CGI.escape(filter_string.join(" :AND: "))}"
96
+ post_body_lines << "Filter=#{escape_filter(filter_string.join(" :AND: "))}"
90
97
  end
91
98
 
92
99
  post_body_lines << "PageNum=#{page}"
@@ -0,0 +1,15 @@
1
+ require 'quickeebooks/online/service/service_base'
2
+ require 'quickeebooks/online/model/time_activity'
3
+ require 'quickeebooks/common/service_crud'
4
+ require 'nokogiri'
5
+
6
+ module Quickeebooks
7
+ module Online
8
+ module Service
9
+ class TimeActivity < ServiceBase
10
+ include ServiceCRUD
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -1,5 +1,5 @@
1
1
  module Quickeebooks
2
2
 
3
- VERSION = "0.1.6"
3
+ VERSION = "0.1.7"
4
4
 
5
5
  end
@@ -45,4 +45,4 @@ describe "Quickeebooks::Online::Model::Customer" do
45
45
  customer.errors.keys.include?(:sync_token).should == true
46
46
  end
47
47
 
48
- end
48
+ end
@@ -0,0 +1,31 @@
1
+ describe "Quickeebooks::Online::Model::Employee" do
2
+
3
+ describe "parse employee from XML" do
4
+ xml = onlineFixture("employee.xml")
5
+ employee = Quickeebooks::Online::Model::Employee.from_xml(xml)
6
+ employee.sync_token.should == 0
7
+ employee.name.should == "John Simpson"
8
+ employee.meta_data.create_time.year.should == Date.civil(2010, 9, 10).year
9
+ employee.addresses.count.should == 1
10
+ employee.addresses.first.line1.should == "21215 Burbank Boulevard, Ste. 100"
11
+ employee.phones.size.should == 2
12
+ employee.phones.first.free_form_number.should == "(818) 936-7800"
13
+ employee.email.address.should == "john.simpson@mint.com"
14
+ end
15
+
16
+ it "can assign an email address" do
17
+ employee = Quickeebooks::Online::Model::Employee.new
18
+ the_email = "foo@example.org"
19
+ employee.email_address = the_email
20
+ employee.email.is_a?(Quickeebooks::Online::Model::Email).should == true
21
+ employee.email.address.should == the_email
22
+ end
23
+
24
+ it "cannot update an invalid model" do
25
+ employee = Quickeebooks::Online::Model::Employee.new
26
+ employee.to_xml_ns.should match('Employee')
27
+ employee.valid_for_update?.should == false
28
+ employee.errors.keys.include?(:sync_token).should == true
29
+ end
30
+
31
+ end
@@ -0,0 +1,83 @@
1
+ describe "Quickeebooks::Online::Service::Employee" do
2
+ before(:all) do
3
+ construct_oauth_service :employee
4
+ end
5
+
6
+ it "can fetch a list of employees" do
7
+ xml = onlineFixture("employees.xml")
8
+ url = @service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_collection)
9
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
10
+ employees = @service.list
11
+ employees.current_page.should == 1
12
+ employees.entries.count.should == 1
13
+ employees.entries.first.name.should == "John Simpson"
14
+ end
15
+
16
+ it "can create a employee" do
17
+ xml = onlineFixture("employee.xml")
18
+ url = @service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)
19
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
20
+ employee = Quickeebooks::Online::Model::Employee.new
21
+ employee.name = "John Doe"
22
+ result = @service.create(employee)
23
+ result.id.value.to_i.should > 0
24
+ end
25
+
26
+ it "can delete a employee" do
27
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)}/11?methodx=delete"
28
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"])
29
+ employee = Quickeebooks::Online::Model::Employee.new
30
+ employee.id = Quickeebooks::Online::Model::Id.new("11")
31
+ employee.sync_token = 0
32
+ result = @service.delete(employee)
33
+ result.should == true
34
+ end
35
+
36
+ it "cannot delete a employee with missing required fields for deletion" do
37
+ employee = Quickeebooks::Online::Model::Employee.new
38
+ expect { @service.delete(employee) }.to raise_exception(InvalidModelException, "Missing required parameters for delete")
39
+ end
40
+
41
+ it "exception is raised when we try to create an invalid account" do
42
+ employee = Quickeebooks::Online::Model::Employee.new
43
+ expect { @service.create(employee) }.to raise_exception InvalidModelException
44
+ end
45
+
46
+ it "cannot update an invalid employee" do
47
+ employee = Quickeebooks::Online::Model::Employee.new
48
+ employee.name = "John Bilby"
49
+ expect { @service.update(employee) }.to raise_exception InvalidModelException
50
+ end
51
+
52
+ it "can fetch a employee by id" do
53
+ xml = onlineFixture("employee.xml")
54
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)}/11"
55
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
56
+ employee = @service.fetch_by_id(11)
57
+ employee.name.should == "John Simpson"
58
+ end
59
+
60
+ it "can update a employee" do
61
+ xml2 = onlineFixture("employee2.xml")
62
+ employee = Quickeebooks::Online::Model::Employee.new
63
+ employee.name = "John Doe"
64
+ employee.id = Quickeebooks::Online::Model::Id.new("1")
65
+ employee.sync_token = 2
66
+
67
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)}/#{employee.id.value}"
68
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml2)
69
+ updated = @service.update(employee)
70
+ updated.name.should == "John Doe"
71
+ end
72
+
73
+ it 'Can update a fetched employee' do
74
+ xml = onlineFixture("employee.xml")
75
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)}/11"
76
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
77
+ employee = @service.fetch_by_id(11)
78
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Employee.resource_for_singular)}/#{employee.id.value}"
79
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
80
+ updated = @service.update(employee)
81
+ end
82
+
83
+ end
@@ -106,6 +106,18 @@ describe "Quickeebooks::Online::Service::ServiceBase" do
106
106
  @service.send(:fetch_collection, @model, [filter])
107
107
  end
108
108
 
109
+ it "with an ampersand in filter value" do
110
+
111
+ filter = Quickeebooks::Online::Service::Filter.new(:text, :field => "Name", :value => "Smith & Gentry")
112
+
113
+ @service.should_receive(:do_http_post).with(@url,
114
+ "Filter=Name+%3AEQUALS%3A+Smith+%2526+Gentry&PageNum=1&ResultsPerPage=20",
115
+ {},
116
+ {"Content-Type"=>"application/x-www-form-urlencoded"})
117
+
118
+ @service.send(:fetch_collection, @model, [filter])
119
+ end
120
+
109
121
  it "paginates" do
110
122
  @service.should_receive(:do_http_post).with(@url,
111
123
  "PageNum=2&ResultsPerPage=20",
@@ -0,0 +1,89 @@
1
+ describe "Quickeebooks::Online::Service::TimeActivity" do
2
+ before(:all) do
3
+ construct_oauth_service :time_activity
4
+ end
5
+
6
+ it "can fetch a list of time activities" do
7
+ xml = onlineFixture("time_activities.xml")
8
+ url = @service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_collection)
9
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
10
+ time_activities = @service.list
11
+ time_activities.current_page.should == 1
12
+ time_activities.entries.count.should == 1
13
+ time_activities.entries.first.vendor.vendor_id.value.should == "3793"
14
+ end
15
+
16
+ it "can create a time activity" do
17
+ xml = onlineFixture("time_activity.xml")
18
+ url = @service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)
19
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
20
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
21
+ time_activity.description = "here is my description"
22
+ time_activity.hourly_rate = "10.5"
23
+ time_activity.name_of = "Vendor"
24
+ time_activity.hours = 10
25
+ time_activity.customer_id = "3794"
26
+ time_activity.minutes = 5
27
+ result = @service.create(time_activity)
28
+ result.id.value.to_i.should > 0
29
+ result.vendor.is_a?(Quickeebooks::Online::Model::TimeActivityVendor)
30
+ end
31
+
32
+ it "can delete a time_activity" do
33
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)}/11?methodx=delete"
34
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"])
35
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
36
+ time_activity.id = Quickeebooks::Online::Model::Id.new("11")
37
+ time_activity.sync_token = 0
38
+ result = @service.delete(time_activity)
39
+ result.should == true
40
+ end
41
+
42
+ it "cannot delete a time_activity with missing required fields for deletion" do
43
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
44
+ expect { @service.delete(time_activity) }.to raise_exception(InvalidModelException, "Missing required parameters for delete")
45
+ end
46
+
47
+ it "exception is raised when we try to create an invalid time_activity" do
48
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
49
+ expect { @service.create(time_activity) }.to raise_exception InvalidModelException
50
+ end
51
+
52
+ it "cannot update an invalid time_activity" do
53
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
54
+ time_activity.name = "John Bilby"
55
+ expect { @service.update(time_activity) }.to raise_exception InvalidModelException
56
+ end
57
+
58
+ it "can fetch a time_activity by id" do
59
+ xml = onlineFixture("time_activity.xml")
60
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)}/11"
61
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
62
+ time_activity = @service.fetch_by_id(11)
63
+ time_activity.vendor.vendor_id.value.should == "3793"
64
+ end
65
+
66
+ it "can update a time_activity" do
67
+ xml2 = onlineFixture("time_activity2.xml")
68
+ time_activity = Quickeebooks::Online::Model::TimeActivity.new
69
+ time_activity.id = Quickeebooks::Online::Model::Id.new("1")
70
+ time_activity.sync_token = 2
71
+
72
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)}/#{time_activity.id.value}"
73
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml2)
74
+ updated = @service.update(time_activity)
75
+ updated.hours.should == 12
76
+ updated.minutes.should == 15
77
+ end
78
+
79
+ it 'Can update a fetched time_activity' do
80
+ xml = onlineFixture("time_activity.xml")
81
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)}/11"
82
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
83
+ time_activity = @service.fetch_by_id(11)
84
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::TimeActivity.resource_for_singular)}/#{time_activity.id.value}"
85
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
86
+ updated = @service.update(time_activity)
87
+ end
88
+
89
+ end
@@ -0,0 +1,18 @@
1
+ describe "Quickeebooks::Online::Model::TimeActivity" do
2
+
3
+ describe "parse time_activity from XML" do
4
+ xml = onlineFixture("time_activity.xml")
5
+ time_activity = Quickeebooks::Online::Model::TimeActivity.from_xml(xml)
6
+ time_activity.sync_token.should == 0
7
+ time_activity.hours.should == 10
8
+ time_activity.minutes.should == 5
9
+ time_activity.billable_status.should == "Billable"
10
+ time_activity.meta_data.create_time.year.should == Date.civil(2010, 9, 13).year
11
+ time_activity.name_of.is_a?(Quickeebooks::Online::Model::TimeActivityVendor)
12
+ time_activity.customer_id.should == "3794"
13
+ time_activity.vendor.vendor_id.value.should == "3793"
14
+
15
+ end
16
+
17
+
18
+ end
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <Employee xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:ns2="http://www.intuit.com/sb/cdm/qbo">
3
+ <Id>13</Id>
4
+ <SyncToken>0</SyncToken>
5
+ <MetaData>
6
+ <CreateTime>2010-09-10T00:55:25-07:00</CreateTime>
7
+ <LastUpdatedTime>2010-09-10T00:55:25-07:00</LastUpdatedTime>
8
+ </MetaData>
9
+ <Name>John Simpson</Name>
10
+ <Address>
11
+ <Line1>21215 Burbank Boulevard, Ste. 100</Line1>
12
+ <Line2></Line2>
13
+ <City>Woodland Hills</City>
14
+ <CountrySubDivisionCode>CA</CountrySubDivisionCode>
15
+ <PostalCode>91367</PostalCode>
16
+ </Address>
17
+ <Phone>
18
+ <FreeFormNumber>(818) 936-7800</FreeFormNumber>
19
+ </Phone>
20
+ <Phone>
21
+ <DeviceType>Mobile</DeviceType>
22
+ <FreeFormNumber>(818) 436-8225</FreeFormNumber>
23
+ </Phone>
24
+ <Email>
25
+ <Address>john.simpson@mint.com</Address>
26
+ </Email>
27
+ <GivenName>John</GivenName>
28
+ <FamilyName>Simpson</FamilyName>
29
+ <BillableTime>false</BillableTime>
30
+ <HiredDate>9999-12-31-08:00</HiredDate>
31
+ </Employee>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <Employee xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:ns2="http://www.intuit.com/sb/cdm/qbo">
3
+ <Id>13</Id>
4
+ <SyncToken>0</SyncToken>
5
+ <MetaData>
6
+ <CreateTime>2010-09-10T00:55:25-07:00</CreateTime>
7
+ <LastUpdatedTime>2010-09-10T00:55:25-07:00</LastUpdatedTime>
8
+ </MetaData>
9
+ <Name>John Doe</Name>
10
+ <Address>
11
+ <Line1>21215 Burbank Boulevard, Ste. 100</Line1>
12
+ <Line2></Line2>
13
+ <City>Woodland Hills</City>
14
+ <CountrySubDivisionCode>CA</CountrySubDivisionCode>
15
+ <PostalCode>91367</PostalCode>
16
+ </Address>
17
+ <Phone>
18
+ <FreeFormNumber>(818) 936-7800</FreeFormNumber>
19
+ </Phone>
20
+ <Phone>
21
+ <DeviceType>Mobile</DeviceType>
22
+ <FreeFormNumber>(818) 436-8225</FreeFormNumber>
23
+ </Phone>
24
+ <Email>
25
+ <Address>john.simpson@mint.com</Address>
26
+ </Email>
27
+ <GivenName>John</GivenName>
28
+ <FamilyName>Simpson</FamilyName>
29
+ <BillableTime>false</BillableTime>
30
+ <HiredDate>9999-12-31-08:00</HiredDate>
31
+ </Employee>