invoiced 0.7.0 → 0.8.0

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/lib/invoiced.rb CHANGED
@@ -19,8 +19,10 @@ require 'invoiced/operations/update'
19
19
  require 'invoiced/object'
20
20
  require 'invoiced/attachment'
21
21
  require 'invoiced/contact'
22
+ require 'invoiced/credit_note'
22
23
  require 'invoiced/customer'
23
24
  require 'invoiced/email'
25
+ require 'invoiced/estimate'
24
26
  require 'invoiced/event'
25
27
  require 'invoiced/file'
26
28
  require 'invoiced/invoice'
@@ -29,114 +31,116 @@ require 'invoiced/subscription'
29
31
  require 'invoiced/transaction'
30
32
 
31
33
  module Invoiced
32
- class Client
33
- ApiBase = 'https://api.invoiced.com'
34
- ApiBaseSandbox = 'https://api.sandbox.invoiced.com'
35
-
36
- attr_reader :api_key, :api_url, :sandbox
37
- attr_reader :Customer, :Event, :File, :Invoice, :Subscription, :Transaction
38
-
39
- def initialize(api_key, sandbox=false)
40
- @api_key = api_key
41
- @sandbox = sandbox
42
- @api_url = sandbox ? ApiBaseSandbox : ApiBase
43
-
44
- # Object endpoints
45
- @Customer = Invoiced::Customer.new(self)
46
- @Event = Invoiced::Event.new(self)
47
- @File = Invoiced::File.new(self)
48
- @Invoice = Invoiced::Invoice.new(self)
49
- @Subscription = Invoiced::Subscription.new(self)
50
- @Transaction = Invoiced::Transaction.new(self)
51
- end
52
-
53
- def request(method, endpoint, params={})
54
- url = @api_url + endpoint
55
-
56
- case method.to_s.downcase.to_sym
57
- # These methods don't have a request body
58
- when :get, :head, :delete
59
- # Make params into GET parameters
60
- url += "#{URI.parse(url).query ? '&' : '?'}#{Util.uri_encode(params)}" if params && params.any?
61
- payload = nil
62
- # Otherwise, encode request body to JSON
63
- else
64
- payload = params.to_json
65
- end
66
-
67
- begin
68
- response = RestClient::Request.execute(
69
- :method => method,
70
- :url => url,
71
- :headers => {
72
- :authorization => Util.auth_header(@api_key),
73
- :content_type => "application/json",
74
- :user_agent => "Invoiced Ruby/#{Invoiced::VERSION}"
75
- },
76
- :payload => payload
77
- )
78
- rescue RestClient::Exception => e
79
- if e.response
80
- rescue_api_error(e.response)
81
- else
82
- rescue_rest_client_error(e)
83
- end
84
- end
85
-
86
- parse(response)
87
- end
88
-
89
- private
90
-
91
- def parse(response)
92
- unless response.code == 204
93
- parsed_response = JSON.parse(response.body, :symbolize_names => true)
94
- else
95
- parsed_response = nil
96
- end
97
-
98
- {
99
- :code => response.code,
100
- :headers => response.headers,
101
- :body => parsed_response
102
- }
103
- end
104
-
105
- def rescue_api_error(response)
106
- begin
107
- error = JSON.parse(response.body)
108
- rescue JSON::ParserError
109
- raise general_api_error(response.code, response.body)
110
- end
111
-
112
- case response.code
113
- when 400, 403, 404
114
- raise invalid_request_error(error, response)
115
- when 401
116
- raise authentication_error(error, response)
117
- else
118
- raise api_error(error, response)
119
- end
120
- end
121
-
122
- def rescue_rest_client_error(error)
123
- raise ApiConnectionError.new("There was an error connecting to Invoiced.")
124
- end
125
-
126
- def authentication_error(error, response)
127
- AuthenticationError.new(error["message"], response.code, error)
128
- end
129
-
130
- def invalid_request_error(error, response)
131
- InvalidRequestError.new(error["message"], response.code, error)
132
- end
133
-
134
- def api_error(error, response)
135
- ApiError.new(error["message"], response.code, error)
136
- end
137
-
138
- def general_api_error(code, body)
139
- ApiError.new("API Error #{code} - #{body}", code)
140
- end
141
- end
34
+ class Client
35
+ ApiBase = 'https://api.invoiced.com'
36
+ ApiBaseSandbox = 'https://api.sandbox.invoiced.com'
37
+
38
+ attr_reader :api_key, :api_url, :sandbox
39
+ attr_reader :CreditNote, :Customer, :Estimate, :Event, :File, :Invoice, :Subscription, :Transaction
40
+
41
+ def initialize(api_key, sandbox=false)
42
+ @api_key = api_key
43
+ @sandbox = sandbox
44
+ @api_url = sandbox ? ApiBaseSandbox : ApiBase
45
+
46
+ # Object endpoints
47
+ @CreditNote = Invoiced::CreditNote.new(self)
48
+ @Customer = Invoiced::Customer.new(self)
49
+ @Estimate = Invoiced::Estimate.new(self)
50
+ @Event = Invoiced::Event.new(self)
51
+ @File = Invoiced::File.new(self)
52
+ @Invoice = Invoiced::Invoice.new(self)
53
+ @Subscription = Invoiced::Subscription.new(self)
54
+ @Transaction = Invoiced::Transaction.new(self)
55
+ end
56
+
57
+ def request(method, endpoint, params={})
58
+ url = @api_url + endpoint
59
+
60
+ case method.to_s.downcase.to_sym
61
+ # These methods don't have a request body
62
+ when :get, :head, :delete
63
+ # Make params into GET parameters
64
+ url += "#{URI.parse(url).query ? '&' : '?'}#{Util.uri_encode(params)}" if params && params.any?
65
+ payload = nil
66
+ # Otherwise, encode request body to JSON
67
+ else
68
+ payload = params.to_json
69
+ end
70
+
71
+ begin
72
+ response = RestClient::Request.execute(
73
+ :method => method,
74
+ :url => url,
75
+ :headers => {
76
+ :authorization => Util.auth_header(@api_key),
77
+ :content_type => "application/json",
78
+ :user_agent => "Invoiced Ruby/#{Invoiced::VERSION}"
79
+ },
80
+ :payload => payload
81
+ )
82
+ rescue RestClient::Exception => e
83
+ if e.response
84
+ rescue_api_error(e.response)
85
+ else
86
+ rescue_rest_client_error(e)
87
+ end
88
+ end
89
+
90
+ parse(response)
91
+ end
92
+
93
+ private
94
+
95
+ def parse(response)
96
+ unless response.code == 204
97
+ parsed_response = JSON.parse(response.body, :symbolize_names => true)
98
+ else
99
+ parsed_response = nil
100
+ end
101
+
102
+ {
103
+ :code => response.code,
104
+ :headers => response.headers,
105
+ :body => parsed_response
106
+ }
107
+ end
108
+
109
+ def rescue_api_error(response)
110
+ begin
111
+ error = JSON.parse(response.body)
112
+ rescue JSON::ParserError
113
+ raise general_api_error(response.code, response.body)
114
+ end
115
+
116
+ case response.code
117
+ when 400, 403, 404
118
+ raise invalid_request_error(error, response)
119
+ when 401
120
+ raise authentication_error(error, response)
121
+ else
122
+ raise api_error(error, response)
123
+ end
124
+ end
125
+
126
+ def rescue_rest_client_error(error)
127
+ raise ApiConnectionError.new("There was an error connecting to Invoiced.")
128
+ end
129
+
130
+ def authentication_error(error, response)
131
+ AuthenticationError.new(error["message"], response.code, error)
132
+ end
133
+
134
+ def invalid_request_error(error, response)
135
+ InvalidRequestError.new(error["message"], response.code, error)
136
+ end
137
+
138
+ def api_error(error, response)
139
+ ApiError.new(error["message"], response.code, error)
140
+ end
141
+
142
+ def general_api_error(code, body)
143
+ ApiError.new("API Error #{code} - #{body}", code)
144
+ end
145
+ end
142
146
  end
@@ -0,0 +1,126 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Invoiced
4
+ class CreditNoteTest < Test::Unit::TestCase
5
+ should "return the api endpoint" do
6
+ creditNote = CreditNote.new(@client, 123)
7
+ assert_equal('/credit_notes/123', creditNote.endpoint())
8
+ end
9
+
10
+ should "create a credit note" do
11
+ mockResponse = mock('RestClient::Response')
12
+ mockResponse.stubs(:code).returns(201)
13
+ mockResponse.stubs(:body).returns('{"id":123,"number":"CN-0001"}')
14
+ mockResponse.stubs(:headers).returns({})
15
+
16
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
17
+
18
+ creditNote = @client.CreditNote.create({:number => "CN-0001"})
19
+
20
+ assert_instance_of(Invoiced::CreditNote, creditNote)
21
+ assert_equal(123, creditNote.id)
22
+ assert_equal('CN-0001', creditNote.number)
23
+ end
24
+
25
+ should "retrieve a credit note" do
26
+ mockResponse = mock('RestClient::Response')
27
+ mockResponse.stubs(:code).returns(200)
28
+ mockResponse.stubs(:body).returns('{"id":123,"number":"CN-0001"}')
29
+ mockResponse.stubs(:headers).returns({})
30
+
31
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
32
+
33
+ creditNote = @client.CreditNote.retrieve(123)
34
+
35
+ assert_instance_of(Invoiced::CreditNote, creditNote)
36
+ assert_equal(123, creditNote.id)
37
+ assert_equal('CN-0001', creditNote.number)
38
+ end
39
+
40
+ should "not update a credit note when no params" do
41
+ creditNote = CreditNote.new(@client, 123)
42
+ assert_false(creditNote.save)
43
+ end
44
+
45
+ should "update a credit note" do
46
+ mockResponse = mock('RestClient::Response')
47
+ mockResponse.stubs(:code).returns(200)
48
+ mockResponse.stubs(:body).returns('{"id":123,"closed":true}')
49
+ mockResponse.stubs(:headers).returns({})
50
+
51
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
52
+
53
+ creditNote = CreditNote.new(@client, 123)
54
+ creditNote.closed = true
55
+ assert_true(creditNote.save)
56
+
57
+ assert_true(creditNote.closed)
58
+ end
59
+
60
+ should "list all credit notes" do
61
+ mockResponse = mock('RestClient::Response')
62
+ mockResponse.stubs(:code).returns(200)
63
+ mockResponse.stubs(:body).returns('[{"id":123,"number":"CN-0001"}]')
64
+ mockResponse.stubs(:headers).returns(:x_total_count => 15, :link => '<https://api.invoiced.com/credit_notes?per_page=25&page=1>; rel="self", <https://api.invoiced.com/credit_notes?per_page=25&page=1>; rel="first", <https://api.invoiced.com/credit_notes?per_page=25&page=1>; rel="last"')
65
+
66
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
67
+
68
+ creditNotes, metadata = @client.CreditNote.list
69
+
70
+ assert_instance_of(Array, creditNotes)
71
+ assert_equal(1, creditNotes.length)
72
+ assert_equal(123, creditNotes[0].id)
73
+
74
+ assert_instance_of(Invoiced::List, metadata)
75
+ assert_equal(15, metadata.total_count)
76
+ end
77
+
78
+ should "delete a credit note" do
79
+ mockResponse = mock('RestClient::Response')
80
+ mockResponse.stubs(:code).returns(204)
81
+ mockResponse.stubs(:body).returns('')
82
+ mockResponse.stubs(:headers).returns({})
83
+
84
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
85
+
86
+ creditNote = CreditNote.new(@client, 123)
87
+ assert_true(creditNote.delete)
88
+ end
89
+
90
+ should "send a credit note" do
91
+ mockResponse = mock('RestClient::Response')
92
+ mockResponse.stubs(:code).returns(201)
93
+ mockResponse.stubs(:body).returns('[{"id":4567,"email":"test@example.com"}]')
94
+ mockResponse.stubs(:headers).returns({})
95
+
96
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
97
+
98
+ creditNote = CreditNote.new(@client, 1234)
99
+ emails = creditNote.send
100
+
101
+ assert_instance_of(Array, emails)
102
+ assert_equal(1, emails.length)
103
+ assert_instance_of(Invoiced::Email, emails[0])
104
+ assert_equal(4567, emails[0].id)
105
+ end
106
+
107
+ should "list all of the credit note's attachments" do
108
+ mockResponse = mock('RestClient::Response')
109
+ mockResponse.stubs(:code).returns(200)
110
+ mockResponse.stubs(:body).returns('[{"file":{"id":456}}]')
111
+ mockResponse.stubs(:headers).returns(:x_total_count => 10, :link => '<https://api.invoiced.com/credit_notes/123/attachments?per_page=25&page=1>; rel="self", <https://api.invoiced.com/credit_notes/123/attachments?per_page=25&page=1>; rel="first", <https://api.invoiced.com/credit_notes/123/attachments?per_page=25&page=1>; rel="last"')
112
+
113
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
114
+
115
+ creditNote = CreditNote.new(@client, 123)
116
+ attachments, metadata = creditNote.attachments
117
+
118
+ assert_instance_of(Array, attachments)
119
+ assert_equal(1, attachments.length)
120
+ assert_equal(456, attachments[0].id)
121
+
122
+ assert_instance_of(Invoiced::List, metadata)
123
+ assert_equal(10, metadata.total_count)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,126 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Invoiced
4
+ class EstimateTest < Test::Unit::TestCase
5
+ should "return the api endpoint" do
6
+ estimate = Estimate.new(@client, 123)
7
+ assert_equal('/estimates/123', estimate.endpoint())
8
+ end
9
+
10
+ should "create an estimate" do
11
+ mockResponse = mock('RestClient::Response')
12
+ mockResponse.stubs(:code).returns(201)
13
+ mockResponse.stubs(:body).returns('{"id":123,"number":"EST-0001"}')
14
+ mockResponse.stubs(:headers).returns({})
15
+
16
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
17
+
18
+ estimate = @client.Estimate.create({:number => "EST-0001"})
19
+
20
+ assert_instance_of(Invoiced::Estimate, estimate)
21
+ assert_equal(123, estimate.id)
22
+ assert_equal('EST-0001', estimate.number)
23
+ end
24
+
25
+ should "retrieve an estimate" do
26
+ mockResponse = mock('RestClient::Response')
27
+ mockResponse.stubs(:code).returns(200)
28
+ mockResponse.stubs(:body).returns('{"id":123,"number":"EST-0001"}')
29
+ mockResponse.stubs(:headers).returns({})
30
+
31
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
32
+
33
+ estimate = @client.Estimate.retrieve(123)
34
+
35
+ assert_instance_of(Invoiced::Estimate, estimate)
36
+ assert_equal(123, estimate.id)
37
+ assert_equal('EST-0001', estimate.number)
38
+ end
39
+
40
+ should "not update an estimate when no params" do
41
+ estimate = Estimate.new(@client, 123)
42
+ assert_false(estimate.save)
43
+ end
44
+
45
+ should "update an estimate" do
46
+ mockResponse = mock('RestClient::Response')
47
+ mockResponse.stubs(:code).returns(200)
48
+ mockResponse.stubs(:body).returns('{"id":123,"closed":true}')
49
+ mockResponse.stubs(:headers).returns({})
50
+
51
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
52
+
53
+ estimate = Estimate.new(@client, 123)
54
+ estimate.closed = true
55
+ assert_true(estimate.save)
56
+
57
+ assert_true(estimate.closed)
58
+ end
59
+
60
+ should "list all estimates" do
61
+ mockResponse = mock('RestClient::Response')
62
+ mockResponse.stubs(:code).returns(200)
63
+ mockResponse.stubs(:body).returns('[{"id":123,"number":"EST-0001"}]')
64
+ mockResponse.stubs(:headers).returns(:x_total_count => 15, :link => '<https://api.invoiced.com/estimates?per_page=25&page=1>; rel="self", <https://api.invoiced.com/estimates?per_page=25&page=1>; rel="first", <https://api.invoiced.com/estimates?per_page=25&page=1>; rel="last"')
65
+
66
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
67
+
68
+ estimates, metadata = @client.Estimate.list
69
+
70
+ assert_instance_of(Array, estimates)
71
+ assert_equal(1, estimates.length)
72
+ assert_equal(123, estimates[0].id)
73
+
74
+ assert_instance_of(Invoiced::List, metadata)
75
+ assert_equal(15, metadata.total_count)
76
+ end
77
+
78
+ should "delete an estimate" do
79
+ mockResponse = mock('RestClient::Response')
80
+ mockResponse.stubs(:code).returns(204)
81
+ mockResponse.stubs(:body).returns('')
82
+ mockResponse.stubs(:headers).returns({})
83
+
84
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
85
+
86
+ estimate = Estimate.new(@client, 123)
87
+ assert_true(estimate.delete)
88
+ end
89
+
90
+ should "send an estimate" do
91
+ mockResponse = mock('RestClient::Response')
92
+ mockResponse.stubs(:code).returns(201)
93
+ mockResponse.stubs(:body).returns('[{"id":4567,"email":"test@example.com"}]')
94
+ mockResponse.stubs(:headers).returns({})
95
+
96
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
97
+
98
+ estimate = Estimate.new(@client, 1234)
99
+ emails = estimate.send
100
+
101
+ assert_instance_of(Array, emails)
102
+ assert_equal(1, emails.length)
103
+ assert_instance_of(Invoiced::Email, emails[0])
104
+ assert_equal(4567, emails[0].id)
105
+ end
106
+
107
+ should "list all of the estimate's attachments" do
108
+ mockResponse = mock('RestClient::Response')
109
+ mockResponse.stubs(:code).returns(200)
110
+ mockResponse.stubs(:body).returns('[{"file":{"id":456}}]')
111
+ mockResponse.stubs(:headers).returns(:x_total_count => 10, :link => '<https://api.invoiced.com/estimates/123/attachments?per_page=25&page=1>; rel="self", <https://api.invoiced.com/estimates/123/attachments?per_page=25&page=1>; rel="first", <https://api.invoiced.com/estimates/123/attachments?per_page=25&page=1>; rel="last"')
112
+
113
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
114
+
115
+ estimate = Estimate.new(@client, 123)
116
+ attachments, metadata = estimate.attachments
117
+
118
+ assert_instance_of(Array, attachments)
119
+ assert_equal(1, attachments.length)
120
+ assert_equal(456, attachments[0].id)
121
+
122
+ assert_instance_of(Invoiced::List, metadata)
123
+ assert_equal(10, metadata.total_count)
124
+ end
125
+ end
126
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: invoiced
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared King
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-12 00:00:00.000000000 Z
11
+ date: 2017-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -124,6 +124,7 @@ files:
124
124
  - lib/invoiced.rb
125
125
  - lib/invoiced/attachment.rb
126
126
  - lib/invoiced/contact.rb
127
+ - lib/invoiced/credit_note.rb
127
128
  - lib/invoiced/customer.rb
128
129
  - lib/invoiced/email.rb
129
130
  - lib/invoiced/error/api_connection_error.rb
@@ -131,6 +132,7 @@ files:
131
132
  - lib/invoiced/error/authentication_error.rb
132
133
  - lib/invoiced/error/error_base.rb
133
134
  - lib/invoiced/error/invalid_request.rb
135
+ - lib/invoiced/estimate.rb
134
136
  - lib/invoiced/event.rb
135
137
  - lib/invoiced/file.rb
136
138
  - lib/invoiced/invoice.rb
@@ -146,8 +148,10 @@ files:
146
148
  - lib/invoiced/util.rb
147
149
  - lib/invoiced/version.rb
148
150
  - test/invoiced/contact_test.rb
151
+ - test/invoiced/credit_note_test.rb
149
152
  - test/invoiced/customer_test.rb
150
153
  - test/invoiced/error_test.rb
154
+ - test/invoiced/estimate_test.rb
151
155
  - test/invoiced/event_test.rb
152
156
  - test/invoiced/file_test.rb
153
157
  - test/invoiced/invoice_test.rb
@@ -184,8 +188,10 @@ specification_version: 4
184
188
  summary: Ruby client library for the Invoiced API
185
189
  test_files:
186
190
  - test/invoiced/contact_test.rb
191
+ - test/invoiced/credit_note_test.rb
187
192
  - test/invoiced/customer_test.rb
188
193
  - test/invoiced/error_test.rb
194
+ - test/invoiced/estimate_test.rb
189
195
  - test/invoiced/event_test.rb
190
196
  - test/invoiced/file_test.rb
191
197
  - test/invoiced/invoice_test.rb