quickeebooks 0.1.6 → 0.1.7

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