freshbooks.rb 3.0.18 → 3.0.25

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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/History.txt +8 -0
  4. data/Manifest.txt +21 -1
  5. data/README.md +61 -0
  6. data/Rakefile +8 -13
  7. data/freshbooks.rb.gemspec +43 -0
  8. data/lib/freshbooks.rb +16 -2
  9. data/lib/freshbooks/address.rb +7 -0
  10. data/lib/freshbooks/api.rb +7 -0
  11. data/lib/freshbooks/autobill.rb +9 -0
  12. data/lib/freshbooks/base.rb +35 -9
  13. data/lib/freshbooks/budget.rb +7 -0
  14. data/lib/freshbooks/card.rb +9 -0
  15. data/lib/freshbooks/client.rb +3 -0
  16. data/lib/freshbooks/connection.rb +34 -25
  17. data/lib/freshbooks/contact.rb +9 -0
  18. data/lib/freshbooks/credits.rb +7 -0
  19. data/lib/freshbooks/estimate.rb +3 -3
  20. data/lib/freshbooks/expiration.rb +8 -0
  21. data/lib/freshbooks/gateway.rb +10 -0
  22. data/lib/freshbooks/gateway_transaction.rb +8 -0
  23. data/lib/freshbooks/invoice.rb +2 -2
  24. data/lib/freshbooks/language.rb +9 -0
  25. data/lib/freshbooks/line.rb +2 -0
  26. data/lib/freshbooks/links.rb +1 -1
  27. data/lib/freshbooks/payment.rb +2 -1
  28. data/lib/freshbooks/project.rb +4 -3
  29. data/lib/freshbooks/recurring.rb +5 -2
  30. data/lib/freshbooks/schema/definition.rb +2 -2
  31. data/lib/freshbooks/staff.rb +5 -0
  32. data/lib/freshbooks/system.rb +14 -0
  33. data/lib/freshbooks/tax.rb +12 -0
  34. data/lib/freshbooks/time_entry.rb +1 -0
  35. data/lib/freshbooks/xml_serializer.rb +5 -0
  36. data/lib/freshbooks/xml_serializer/serializers.rb +2 -2
  37. data/test/fixtures/freshbooks_credentials.yml +3 -0
  38. data/test/fixtures/recurring_create_response.xml +4 -0
  39. data/test/fixtures/recurring_get_response.xml +59 -0
  40. data/test/fixtures/recurring_list_response.xml +61 -0
  41. data/test/live_connection_test.rb +28 -0
  42. data/test/test_base.rb +59 -0
  43. data/test/test_connection.rb +39 -32
  44. data/test/test_helper.rb +20 -5
  45. data/test/test_invoice.rb +23 -37
  46. data/test/test_recurring.rb +98 -0
  47. metadata +67 -46
  48. data/README +0 -44
@@ -0,0 +1,9 @@
1
+ module FreshBooks
2
+ class Contact < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.string :email, :username, :first_name, :last_name, :phone1, :phone2
5
+ end
6
+
7
+ actions :list, :get, :create, :update, :delete
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module FreshBooks
2
+ class Credits < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.string :credit, :currency, :read_only => true
5
+ end
6
+ end
7
+ end
@@ -1,10 +1,10 @@
1
1
  module FreshBooks
2
2
  class Estimate < FreshBooks::Base
3
3
  define_schema do |s|
4
- s.string :estimate_id, :status, :date, :notes, :terms, :first_name
4
+ s.string :estimate_id, :status, :date, :notes, :terms, :first_name, :number
5
5
  s.string :last_name, :organization, :p_street1, :p_street2, :p_city
6
- s.string :p_state, :p_country, :p_code
7
- s.fixnum :client_id, :po_number
6
+ s.string :p_state, :p_country, :p_code, :currency_code, :language
7
+ s.fixnum :client_id, :po_number, :staff_id
8
8
  s.float :discount, :amount
9
9
  s.array :lines
10
10
  s.object :links, :read_only => true
@@ -0,0 +1,8 @@
1
+ module FreshBooks
2
+ class Expiration < FreshBooks::Base
3
+
4
+ define_schema do |s|
5
+ s.string :month, :year
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module FreshBooks
2
+ class Gateway < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.string :name
5
+ s.boolean :autobill_capable
6
+ end
7
+
8
+ actions :list
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module FreshBooks
2
+ class GatewayTransaction < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.fixnum :reference_id
5
+ s.string :gateway_name
6
+ end
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
1
  module FreshBooks
2
2
  class Invoice < FreshBooks::Base
3
3
  define_schema do |s|
4
- s.fixnum :invoice_id, :client_id, :po_number
4
+ s.fixnum :invoice_id, :client_id, :po_number, :staff_id
5
5
  s.fixnum :recurring_id, :read_only => true
6
6
  s.float :amount, :discount
7
7
  s.float :amount_outstanding, :paid, :read_only => true
@@ -9,7 +9,7 @@ module FreshBooks
9
9
  s.date_time :updated, :read_only => true
10
10
  s.array :lines
11
11
  s.object :links, :read_only => true
12
- s.string :number, :organization, :status, :notes, :terms, :first_name, :last_name
12
+ s.string :number, :organization, :status, :notes, :terms, :first_name, :last_name, :currency_code, :language
13
13
  s.string :p_street1, :p_street2, :p_city, :p_state, :p_country, :p_code
14
14
  s.string :return_uri
15
15
  end
@@ -0,0 +1,9 @@
1
+ module FreshBooks
2
+ class Language < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.string :code, :name
5
+ end
6
+
7
+ actions :list
8
+ end
9
+ end
@@ -1,7 +1,9 @@
1
1
  module FreshBooks
2
2
  class Line < FreshBooks::Base
3
+
3
4
  define_schema do |s|
4
5
  s.string :name, :description, :tax1_name, :tax2_name
6
+ s.string :type
5
7
  s.float :unit_cost, :tax1_percent, :tax2_percent
6
8
  s.float :amount, :read_only => true
7
9
  s.float :quantity
@@ -1,7 +1,7 @@
1
1
  module FreshBooks
2
2
  class Links < FreshBooks::Base
3
3
  define_schema do |s|
4
- s.string :client_view, :view, :edit, :read_only => true
4
+ s.string :client_view, :view, :edit, :statement, :read_only => true
5
5
  end
6
6
  end
7
7
  end
@@ -5,7 +5,8 @@ module FreshBooks
5
5
  s.float :amount
6
6
  s.date :date
7
7
  s.date_time :updated, :read_only => true
8
- s.string :type, :notes
8
+ s.string :type, :notes, :currency_code
9
+ s.object :gateway_transaction
9
10
  end
10
11
 
11
12
  actions :list, :get, :create, :update, :delete
@@ -3,10 +3,11 @@ module FreshBooks
3
3
  define_schema do |s|
4
4
  s.string :name, :bill_method, :description
5
5
  s.fixnum :project_id, :client_id
6
- s.float :rate
7
- s.array :tasks
6
+ s.float :rate, :hour_budget
7
+ s.array :tasks, :staff
8
+ s.object :budget
8
9
  end
9
10
 
10
11
  actions :list, :get, :create, :update, :delete
11
12
  end
12
- end
13
+ end
@@ -2,14 +2,17 @@ module FreshBooks
2
2
  class Recurring < FreshBooks::Base
3
3
  define_schema do |s|
4
4
  s.string :first_name, :last_name, :organization, :p_street1, :p_street2, :p_city
5
- s.string :p_state, :p_country, :p_code, :lines, :status, :notes, :terms, :frequency
5
+ s.string :p_state, :p_country, :p_code, :lines, :notes, :terms, :frequency
6
+ s.string :currency_code, :language
6
7
  s.date :date
7
8
  s.fixnum :recurring_id, :client_id, :po_number, :occurrences
8
9
  s.float :discount, :amount
9
10
  s.array :lines
10
11
  s.boolean :stopped, :send_email, :send_snail_mail
12
+ s.string :return_uri
13
+ s.object :autobill
11
14
  end
12
-
15
+
13
16
  actions :list, :get, :create, :update, :delete
14
17
  end
15
18
  end
@@ -4,7 +4,7 @@ module FreshBooks
4
4
  attr_reader :members
5
5
 
6
6
  def initialize
7
- @members = {}
7
+ @members = ActiveSupport::OrderedHash.new
8
8
  end
9
9
 
10
10
  def method_missing(method, *attributes)
@@ -17,4 +17,4 @@ module FreshBooks
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -9,5 +9,10 @@ module FreshBooks
9
9
  end
10
10
 
11
11
  actions :list, :get
12
+
13
+ def self.current
14
+ response = FreshBooks::Base.connection.call_api("#{api_class_name}.current")
15
+ response.success? ? self.new_from_xml(response.elements[1]) : nil
16
+ end
12
17
  end
13
18
  end
@@ -0,0 +1,14 @@
1
+ module FreshBooks
2
+ class System < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.string :company_name, :profession
5
+ s.object :address
6
+ s.object :api
7
+ end
8
+
9
+ def self.current
10
+ response = FreshBooks::Base.connection.call_api("#{api_class_name}.current")
11
+ response.success? ? self.new_from_xml(response.elements[1]) : nil
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module FreshBooks
2
+ class Tax < FreshBooks::Base
3
+ define_schema do |s|
4
+ s.fixnum :tax_id
5
+ s.float :rate
6
+ s.boolean :compound
7
+ s.string :name, :number
8
+ end
9
+
10
+ actions :list, :get, :create, :update, :delete
11
+ end
12
+ end
@@ -5,6 +5,7 @@ module FreshBooks
5
5
  s.float :hours
6
6
  s.date :date
7
7
  s.string :notes
8
+ s.boolean :billed
8
9
  end
9
10
 
10
11
  actions :list, :get, :create, :update, :delete
@@ -13,5 +13,10 @@ module FreshBooks
13
13
  def self.create_serializer(type)
14
14
  "FreshBooks::XmlSerializer::#{type.to_s.classify}Serializer".constantize
15
15
  end
16
+
17
+ def self.deprecated?(node)
18
+ !node.attribute('deprecated').nil?
19
+ end
20
+
16
21
  end
17
22
  end
@@ -86,8 +86,8 @@ module FreshBooks
86
86
 
87
87
  def self.to_value(xml_val)
88
88
  xml_val.elements.map { |elem|
89
- FreshBooks::const_get(elem.name.camelize)::new_from_xml(elem)
90
- }
89
+ FreshBooks::const_get(elem.name.camelize)::new_from_xml(elem) unless XmlSerializer.deprecated? elem
90
+ }.compact
91
91
  end
92
92
  end
93
93
 
@@ -0,0 +1,3 @@
1
+ fresh_books_test_account:
2
+ account_url: outright.freshbooks.com
3
+ api_key: 569916aa36f9f52a3a84424a8e55fc05
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <response status="ok">
3
+ <recurring_id>1</recurring_id>
4
+ </response>
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0"?>
2
+ <response status="ok">
3
+ <recurring>
4
+ <recurring_id>1</recurring_id>
5
+
6
+ <frequency>m</frequency>
7
+ <occurrences>1</occurrences>
8
+ <stopped>0</stopped>
9
+
10
+ <client_id>1</client_id>
11
+ <amount>100.0</amount>
12
+ <date>2011-04-01</date>
13
+
14
+ <po_number>1</po_number>
15
+ <discount>1.0</discount>
16
+ <notes>notes1</notes>
17
+ <terms>terms1</terms>
18
+
19
+ <first_name>first_name1</first_name>
20
+ <last_name>last_name1</last_name>
21
+ <organization>organization1</organization>
22
+ <p_street1>p_street11</p_street1>
23
+ <p_street2>p_street21</p_street2>
24
+ <p_city>p_city1</p_city>
25
+ <p_state>p_state1</p_state>
26
+ <p_country>p_country1</p_country>
27
+ <p_code>p_code1</p_code>
28
+
29
+ <return_uri>return_uri1</return_uri>
30
+ <send_email>1</send_email>
31
+ <send_snail_mail>0</send_snail_mail>
32
+
33
+ <autobill>
34
+ <gateway_name>gateway1</gateway_name>
35
+ <card>
36
+ <number>1</number>
37
+ <name>name1</name>
38
+ <expiration>
39
+ <month>01</month>
40
+ <year>2001</year>
41
+ </expiration>
42
+ </card>
43
+ </autobill>
44
+
45
+ <lines>
46
+ <line>
47
+ <amount>1.0</amount>
48
+ <name>name1</name>
49
+ <description>description1</description>
50
+ <tax1_name>tax1_name1</tax1_name>
51
+ <tax2_name>tax2_name1</tax2_name>
52
+ <unit_cost>1.0</unit_cost>
53
+ <tax1_percent>1.0</tax1_percent>
54
+ <tax2_percent>1.0</tax2_percent>
55
+ <quantity>1</quantity>
56
+ </line>
57
+ </lines>
58
+ </recurring>
59
+ </response>
@@ -0,0 +1,61 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <response xmlns="http://www.freshbooks.com/api/" status="ok">
3
+ <recurrings page="1" per_page="1" pages="1" total="1">
4
+ <recurring>
5
+ <recurring_id>1</recurring_id>
6
+
7
+ <frequency>m</frequency>
8
+ <occurrences>1</occurrences>
9
+ <stopped>0</stopped>
10
+
11
+ <client_id>1</client_id>
12
+ <amount>100.0</amount>
13
+ <date>2011-04-01</date>
14
+
15
+ <po_number>1</po_number>
16
+ <discount>1.0</discount>
17
+ <notes>notes1</notes>
18
+ <terms>terms1</terms>
19
+
20
+ <first_name>first_name1</first_name>
21
+ <last_name>last_name1</last_name>
22
+ <organization>organization1</organization>
23
+ <p_street1>p_street11</p_street1>
24
+ <p_street2>p_street21</p_street2>
25
+ <p_city>p_city1</p_city>
26
+ <p_state>p_state1</p_state>
27
+ <p_country>p_country1</p_country>
28
+ <p_code>p_code1</p_code>
29
+
30
+ <return_uri>return_uri1</return_uri>
31
+ <send_email>1</send_email>
32
+ <send_snail_mail>0</send_snail_mail>
33
+
34
+ <autobill>
35
+ <gateway_name>gateway1</gateway_name>
36
+ <card>
37
+ <number>1</number>
38
+ <name>name1</name>
39
+ <expiration>
40
+ <month>01</month>
41
+ <year>2001</year>
42
+ </expiration>
43
+ </card>
44
+ </autobill>
45
+
46
+ <lines>
47
+ <line>
48
+ <amount>1.0</amount>
49
+ <name>name1</name>
50
+ <description>description1</description>
51
+ <tax1_name>tax1_name1</tax1_name>
52
+ <tax2_name>tax2_name1</tax2_name>
53
+ <unit_cost>1.0</unit_cost>
54
+ <tax1_percent>1.0</tax1_percent>
55
+ <tax2_percent>1.0</tax2_percent>
56
+ <quantity>1</quantity>
57
+ </line>
58
+ </lines>
59
+ </recurring>
60
+ </recurrings>
61
+ </response>
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ # this tests a live conection
4
+ class LiveConnectionTest < Test::Unit::TestCase
5
+ fixtures :freshbooks_credentials
6
+
7
+ def setup
8
+ fb_account_info = freshbooks_credentials(:fresh_books_test_account)
9
+ FreshBooks::Base.establish_connection(fb_account_info['account_url'], fb_account_info['api_key'])
10
+ end
11
+
12
+ # just go out there and get a live connection and see if it returns anything
13
+ def test_live_connection_with_start_session
14
+ FreshBooks::Base.connection.start_session do
15
+ clients = FreshBooks::Client.list("per_page" => 1)
16
+ FreshBooks::Invoice.list("per_page" => 100).collect do |invoice|
17
+ assert FreshBooks::Invoice.get(invoice.invoice_id)
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_live_connection_without_start_session
23
+ clients = FreshBooks::Client.list("per_page" => 1)
24
+ FreshBooks::Invoice.list("per_page" => 100).collect do |invoice|
25
+ assert FreshBooks::Invoice.get(invoice.invoice_id)
26
+ end
27
+ end
28
+ end
@@ -66,6 +66,56 @@ class TestBase < Test::Unit::TestCase
66
66
  assert xml_out.include?("<my_lines><my_line><description>description</description></my_line></my_lines>")
67
67
  end
68
68
 
69
+ def test_create_objects_with_initializer_arguments
70
+ invoice_1 = FreshBooks::Invoice.new
71
+ invoice_1.client_id = 1
72
+ invoice_1.lines = [FreshBooks::Line.new, FreshBooks::Line.new]
73
+ invoice_1.lines[0].name = "Awesomeness"
74
+ invoice_1.lines[0].unit_cost = 9999
75
+ invoice_1.lines[0].quantity = 42
76
+ invoice_1.lines[1].name = "Ninja skills"
77
+ invoice_1.lines[1].unit_cost = 349
78
+ invoice_1.lines[1].quantity = 100
79
+
80
+ invoice_2 = FreshBooks::Invoice.new(
81
+ :client_id => 1,
82
+ :lines => [
83
+ FreshBooks::Line.new(
84
+ :name => "Awesomeness",
85
+ :unit_cost => 9999,
86
+ :quantity => 42
87
+ ),
88
+ FreshBooks::Line.new(
89
+ :name => "Ninja skills",
90
+ :unit_cost => 349,
91
+ :quantity => 100
92
+ )
93
+ ]
94
+ )
95
+
96
+ assert_equal invoice_1.to_xml, invoice_2.to_xml
97
+ end
98
+
99
+ def test_can_handle_all_zero_updated_at
100
+ xml = <<-END_XML
101
+ <my_client>
102
+ <client_id>3</client_id>
103
+ <first_name>Test</first_name>
104
+ <last_name>User</last_name>
105
+ <organization>User Testing</organization>
106
+ <updated>0000-00-00 00:00:00</updated>
107
+ </my_client>
108
+ END_XML
109
+ doc = REXML::Document.new(xml)
110
+
111
+ item = FreshBooks::MyClient.new_from_xml(doc.root)
112
+ assert_equal nil, item.updated
113
+ end
114
+
115
+ def test_actions
116
+ assert FreshBooks::MyItem.respond_to?(:get)
117
+ assert !Class.new.respond_to?(:get)
118
+ end
69
119
  end
70
120
 
71
121
  module FreshBooks
@@ -81,6 +131,15 @@ module FreshBooks
81
131
  s.object :my_address
82
132
  s.array :my_lines
83
133
  end
134
+ actions :get
135
+ end
136
+
137
+ class MyClient < FreshBooks::Base
138
+ define_schema do |s|
139
+ s.string :first_name, :last_name, :organization
140
+ s.fixnum :client_id
141
+ s.date_time :updated
142
+ end
84
143
  end
85
144
 
86
145
  class MyAddress < FreshBooks::Base