invoiced 0.12.0 → 1.2.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.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -1
  3. data/.travis.yml +5 -1
  4. data/Gemfile +6 -2
  5. data/README.md +4 -2
  6. data/invoiced.gemspec +2 -8
  7. data/lib/invoiced.rb +43 -5
  8. data/lib/invoiced/attachment.rb +1 -0
  9. data/lib/invoiced/bank_account.rb +6 -0
  10. data/lib/invoiced/card.rb +6 -0
  11. data/lib/invoiced/catalog_item.rb +2 -0
  12. data/lib/invoiced/charge.rb +12 -0
  13. data/lib/invoiced/contact.rb +2 -0
  14. data/lib/invoiced/coupon.rb +10 -0
  15. data/lib/invoiced/credit_note.rb +10 -0
  16. data/lib/invoiced/customer.rb +36 -0
  17. data/lib/invoiced/email.rb +1 -0
  18. data/lib/invoiced/estimate.rb +10 -0
  19. data/lib/invoiced/event.rb +2 -0
  20. data/lib/invoiced/file.rb +2 -0
  21. data/lib/invoiced/invoice.rb +33 -1
  22. data/lib/invoiced/letter.rb +5 -0
  23. data/lib/invoiced/line_item.rb +2 -0
  24. data/lib/invoiced/note.rb +10 -0
  25. data/lib/invoiced/object.rb +11 -5
  26. data/lib/invoiced/operations/create.rb +1 -1
  27. data/lib/invoiced/payment.rb +18 -0
  28. data/lib/invoiced/payment_plan.rb +2 -0
  29. data/lib/invoiced/payment_source.rb +8 -0
  30. data/lib/invoiced/payment_source_object.rb +5 -0
  31. data/lib/invoiced/plan.rb +2 -0
  32. data/lib/invoiced/refund.rb +11 -0
  33. data/lib/invoiced/subscription.rb +8 -0
  34. data/lib/invoiced/task.rb +10 -0
  35. data/lib/invoiced/tax_rate.rb +10 -0
  36. data/lib/invoiced/text_message.rb +5 -0
  37. data/lib/invoiced/transaction.rb +8 -0
  38. data/lib/invoiced/util.rb +13 -1
  39. data/lib/invoiced/version.rb +1 -1
  40. data/test/invoiced/charge_test.rb +25 -0
  41. data/test/invoiced/coupon_test.rb +90 -0
  42. data/test/invoiced/credit_note_test.rb +14 -0
  43. data/test/invoiced/customer_test.rb +101 -2
  44. data/test/invoiced/estimate_test.rb +14 -0
  45. data/test/invoiced/invoice_test.rb +69 -1
  46. data/test/invoiced/invoiced_test.rb +27 -1
  47. data/test/invoiced/note_test.rb +90 -0
  48. data/test/invoiced/payment_source_test.rb +57 -0
  49. data/test/invoiced/payment_test.rb +107 -0
  50. data/test/invoiced/refund_test.rb +25 -0
  51. data/test/invoiced/subscription_test.rb +13 -0
  52. data/test/invoiced/task_test.rb +90 -0
  53. data/test/invoiced/tax_rate_test.rb +90 -0
  54. data/test/invoiced/transaction_test.rb +15 -0
  55. metadata +36 -78
@@ -0,0 +1,5 @@
1
+ module Invoiced
2
+ class Letter < Object
3
+ OBJECT_NAME = 'letter'
4
+ end
5
+ end
@@ -4,5 +4,7 @@ module Invoiced
4
4
  include Invoiced::Operations::Create
5
5
  include Invoiced::Operations::Update
6
6
  include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'line_item'
7
9
  end
8
10
  end
@@ -0,0 +1,10 @@
1
+ module Invoiced
2
+ class Note < Object
3
+ include Invoiced::Operations::List
4
+ include Invoiced::Operations::Create
5
+ include Invoiced::Operations::Update
6
+ include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'note'
9
+ end
10
+ end
@@ -8,10 +8,8 @@ module Invoiced
8
8
 
9
9
  def initialize(client, id=nil, values={})
10
10
  @client = client
11
- class_name = self.class.name.split('::').last
12
11
  @endpoint_base = ''
13
- @endpoint = '/' + class_name.underscore.pluralize.downcase
14
-
12
+ @endpoint = build_endpoint
15
13
  @id = id
16
14
  @values = {}
17
15
 
@@ -35,12 +33,20 @@ module Invoiced
35
33
  @endpoint_base + @endpoint
36
34
  end
37
35
 
36
+ def build_endpoint
37
+ if self.class.const_defined? "OBJECT_NAME"
38
+ '/' + self.class::OBJECT_NAME + 's'
39
+ else
40
+ '/objects'
41
+ end
42
+ end
43
+
38
44
  def retrieve(id, params={})
39
45
  if !id
40
46
  raise ArgumentError.new("Missing ID.")
41
47
  end
42
48
 
43
- response = @client.request(:get, "#{self.endpoint()}/#{id}", params)
49
+ response = @client.request(:get, "#{endpoint()}/#{id}", params)
44
50
 
45
51
  Util.convert_to_object(self, response[:body])
46
52
  end
@@ -51,7 +57,7 @@ module Invoiced
51
57
 
52
58
  def inspect
53
59
  id_string = (!@id.nil?) ? " id=#{@id}" : ""
54
- "#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
60
+ "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
55
61
  end
56
62
 
57
63
  def refresh_from(values)
@@ -2,7 +2,7 @@ module Invoiced
2
2
  module Operations
3
3
  module Create
4
4
  def create(body={}, opts={})
5
- response = @client.request(:post, self.endpoint(), body, opts)
5
+ response = @client.request(:post, endpoint(), body, opts)
6
6
 
7
7
  Util.convert_to_object(self, response[:body])
8
8
  end
@@ -0,0 +1,18 @@
1
+ module Invoiced
2
+ class Payment < Object
3
+ include Invoiced::Operations::List
4
+ include Invoiced::Operations::Create
5
+ include Invoiced::Operations::Update
6
+ include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'payment'
9
+
10
+ def send(params={}, opts={})
11
+ response = @client.request(:post, "#{self.endpoint()}/emails", params, opts)
12
+
13
+ # build email objects
14
+ email = Email.new(@client)
15
+ Util.build_objects(email, response[:body])
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,8 @@ module Invoiced
2
2
  class PaymentPlan < Object
3
3
  include Invoiced::Operations::Delete
4
4
 
5
+ OBJECT_NAME = 'payment_plan'
6
+
5
7
  def initialize(client, id=nil, values={})
6
8
  super
7
9
  @endpoint = '/payment_plan'
@@ -0,0 +1,8 @@
1
+ module Invoiced
2
+ class PaymentSource < Object
3
+ include Invoiced::Operations::Create
4
+ include Invoiced::Operations::List
5
+
6
+ OBJECT_NAME = 'payment_source'
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Invoiced
2
+ class PaymentSourceObject < Object
3
+ include Invoiced::Operations::Delete
4
+ end
5
+ end
@@ -4,5 +4,7 @@ module Invoiced
4
4
  include Invoiced::Operations::Create
5
5
  include Invoiced::Operations::Update
6
6
  include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'plan'
7
9
  end
8
10
  end
@@ -0,0 +1,11 @@
1
+ module Invoiced
2
+ class Refund < Object
3
+ OBJECT_NAME = 'refund'
4
+
5
+ def create(chargeId, body={}, opts={})
6
+ response = @client.request(:post, @endpoint_base + "/charges/#{chargeId}/refunds", body, opts)
7
+
8
+ Util.convert_to_object(self, response[:body])
9
+ end
10
+ end
11
+ end
@@ -5,8 +5,16 @@ module Invoiced
5
5
  include Invoiced::Operations::Update
6
6
  include Invoiced::Operations::Delete
7
7
 
8
+ OBJECT_NAME = 'subscription'
9
+
8
10
  def cancel
9
11
  delete
10
12
  end
13
+
14
+ def preview(params={}, opts={})
15
+ response = @client.request(:post, "/subscriptions/preview", params, opts)
16
+
17
+ response[:body]
18
+ end
11
19
  end
12
20
  end
@@ -0,0 +1,10 @@
1
+ module Invoiced
2
+ class Task < Object
3
+ include Invoiced::Operations::List
4
+ include Invoiced::Operations::Create
5
+ include Invoiced::Operations::Update
6
+ include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'task'
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Invoiced
2
+ class TaxRate < Object
3
+ include Invoiced::Operations::List
4
+ include Invoiced::Operations::Create
5
+ include Invoiced::Operations::Update
6
+ include Invoiced::Operations::Delete
7
+
8
+ OBJECT_NAME = 'tax_rate'
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Invoiced
2
+ class TextMessage < Object
3
+ OBJECT_NAME = 'text_message'
4
+ end
5
+ end
@@ -5,6 +5,8 @@ module Invoiced
5
5
  include Invoiced::Operations::Update
6
6
  include Invoiced::Operations::Delete
7
7
 
8
+ OBJECT_NAME = 'transaction'
9
+
8
10
  def send(params={}, opts={})
9
11
  response = @client.request(:post, "#{self.endpoint()}/emails", params, opts)
10
12
 
@@ -18,5 +20,11 @@ module Invoiced
18
20
 
19
21
  Util.convert_to_object(self, response[:body])
20
22
  end
23
+
24
+ def initiate_charge(params={}, opts={})
25
+ response = @client.request(:post, "/charges", params, opts)
26
+
27
+ Util.convert_to_object(self, response[:body])
28
+ end
21
29
  end
22
30
  end
@@ -17,7 +17,19 @@ module Invoiced
17
17
  end
18
18
 
19
19
  def convert_to_object(_class, values)
20
- object = _class.class.new(_class.client, values[:id], values)
20
+ object_class = _class.class
21
+
22
+ # check for PaymentSource special case where class must be forced to Card or BankAccount
23
+ unless values[:object].nil?
24
+ if values[:object] == 'card'
25
+ object_class = Invoiced::Card
26
+ elsif values[:object] == 'bank_account'
27
+ object_class = Invoiced::BankAccount
28
+ end
29
+ end
30
+
31
+ object = object_class.new(_class.client, values[:id], values)
32
+
21
33
  object.set_endpoint_base(_class.endpoint_base())
22
34
  end
23
35
 
@@ -1,3 +1,3 @@
1
1
  module Invoiced
2
- VERSION = '0.12.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Invoiced
4
+ class ChargeTest < Test::Unit::TestCase
5
+ should "return the api endpoint" do
6
+ charge = Charge.new(@client, 123)
7
+ assert_equal('/charges/123', charge.endpoint())
8
+ end
9
+
10
+ should "create a charge" do
11
+ mockResponse = mock('RestClient::Response')
12
+ mockResponse.stubs(:code).returns(201)
13
+ mockResponse.stubs(:body).returns('{"id":"a1b2c3","amount":100,"object":"charge"}')
14
+ mockResponse.stubs(:headers).returns({})
15
+
16
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
17
+
18
+ charge = Charge.new(@client, 1234)
19
+ charge = charge.create(:amount => 100, :payment_source_type => "card")
20
+
21
+ assert_instance_of(Invoiced::Payment, charge)
22
+ assert_equal(charge.id, "a1b2c3")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Invoiced
4
+ class CouponTest < Test::Unit::TestCase
5
+ should "return the api endpoint" do
6
+ coupon = Coupon.new(@client, "test")
7
+ assert_equal('/coupons/test', coupon.endpoint())
8
+ end
9
+
10
+ should "create a coupon" do
11
+ mockResponse = mock('RestClient::Response')
12
+ mockResponse.stubs(:code).returns(201)
13
+ mockResponse.stubs(:body).returns('{"id":"test","name":"Test Coupon"}')
14
+ mockResponse.stubs(:headers).returns({})
15
+
16
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
17
+
18
+ coupon = @client.Coupon.create({:name => "Test Coupon"})
19
+
20
+ assert_instance_of(Invoiced::Coupon, coupon)
21
+ assert_equal("test", coupon.id)
22
+ assert_equal('Test Coupon', coupon.name)
23
+ end
24
+
25
+ should "retrieve a coupon" do
26
+ mockResponse = mock('RestClient::Response')
27
+ mockResponse.stubs(:code).returns(200)
28
+ mockResponse.stubs(:body).returns('{"id":"test","name":"Test Coupon"}')
29
+ mockResponse.stubs(:headers).returns({})
30
+
31
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
32
+
33
+ coupon = @client.Coupon.retrieve("test")
34
+
35
+ assert_instance_of(Invoiced::Coupon, coupon)
36
+ assert_equal("test", coupon.id)
37
+ assert_equal('Test Coupon', coupon.name)
38
+ end
39
+
40
+ should "not update a coupon when no params" do
41
+ coupon = Coupon.new(@client, "test")
42
+ assert_false(coupon.save)
43
+ end
44
+
45
+ should "update a coupon" do
46
+ mockResponse = mock('RestClient::Response')
47
+ mockResponse.stubs(:code).returns(200)
48
+ mockResponse.stubs(:body).returns('{"id":"test","name":"Testing Coupon"}')
49
+ mockResponse.stubs(:headers).returns({})
50
+
51
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
52
+
53
+ coupon = Coupon.new(@client, "test")
54
+ coupon.name = "Testing Coupon"
55
+ assert_true(coupon.save)
56
+
57
+ assert_equal(coupon.name, "Testing Coupon")
58
+ end
59
+
60
+ should "list all coupons" do
61
+ mockResponse = mock('RestClient::Response')
62
+ mockResponse.stubs(:code).returns(200)
63
+ mockResponse.stubs(:body).returns('[{"id":"test","name":"Test Coupon"}]')
64
+ mockResponse.stubs(:headers).returns(:x_total_count => 15, :link => '<https://api.invoiced.com/catalog_items?per_page=25&page=1>; rel="self", <https://api.invoiced.com/catalog_items?per_page=25&page=1>; rel="first", <https://api.invoiced.com/catalog_items?per_page=25&page=1>; rel="last"')
65
+
66
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
67
+
68
+ coupons, metadata = @client.Coupon.list
69
+
70
+ assert_instance_of(Array, coupons)
71
+ assert_equal(1, coupons.length)
72
+ assert_equal("test", coupons[0].id)
73
+
74
+ assert_instance_of(Invoiced::List, metadata)
75
+ assert_equal(15, metadata.total_count)
76
+ end
77
+
78
+ should "delete a coupon" 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
+ coupon = Coupon.new(@client, "test")
87
+ assert_true(coupon.delete)
88
+ end
89
+ end
90
+ end
@@ -122,5 +122,19 @@ module Invoiced
122
122
  assert_instance_of(Invoiced::List, metadata)
123
123
  assert_equal(10, metadata.total_count)
124
124
  end
125
+
126
+ should "void a credit note" do
127
+ mockResponse = mock('RestClient::Response')
128
+ mockResponse.stubs(:code).returns(200)
129
+ mockResponse.stubs(:body).returns('{"id":123,"status":"voided"}')
130
+ mockResponse.stubs(:headers).returns({})
131
+
132
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
133
+
134
+ credit_note = CreditNote.new(@client, 123)
135
+ assert_true(credit_note.void)
136
+
137
+ assert_equal(credit_note.status, 'voided')
138
+ end
125
139
  end
126
140
  end
@@ -87,7 +87,7 @@ module Invoiced
87
87
  assert_true(customer.delete)
88
88
  end
89
89
 
90
- should "send an account statement" do
90
+ should "send an account statement by email" do
91
91
  mockResponse = mock('RestClient::Response')
92
92
  mockResponse.stubs(:code).returns(201)
93
93
  mockResponse.stubs(:body).returns('[{"id":4567,"email":"test@example.com"}]')
@@ -104,6 +104,40 @@ module Invoiced
104
104
  assert_equal(4567, emails[0].id)
105
105
  end
106
106
 
107
+ should "send an account statement by text message" do
108
+ mockResponse = mock('RestClient::Response')
109
+ mockResponse.stubs(:code).returns(201)
110
+ mockResponse.stubs(:body).returns('[{"id":5678,"state":"sent"}]')
111
+ mockResponse.stubs(:headers).returns({})
112
+
113
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
114
+
115
+ customer = Customer.new(@client, 123)
116
+ text_messages = customer.send_statement_sms(:type => "open_item", :message => "example")
117
+
118
+ assert_instance_of(Array, text_messages)
119
+ assert_equal(1, text_messages.length)
120
+ assert_instance_of(Invoiced::TextMessage, text_messages[0])
121
+ assert_equal(5678, text_messages[0].id)
122
+ end
123
+
124
+ should "send an account statement by letter" do
125
+ mockResponse = mock('RestClient::Response')
126
+ mockResponse.stubs(:code).returns(201)
127
+ mockResponse.stubs(:body).returns('[{"id":6789,"state":"queued"}]')
128
+ mockResponse.stubs(:headers).returns({})
129
+
130
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
131
+
132
+ customer = Customer.new(@client, 123)
133
+ letters = customer.send_statement_letter(:type => "open_item")
134
+
135
+ assert_instance_of(Array, letters)
136
+ assert_equal(1, letters.length)
137
+ assert_instance_of(Invoiced::Letter, letters[0])
138
+ assert_equal(6789, letters[0].id)
139
+ end
140
+
107
141
  should "retrieve a customer's balance" do
108
142
  mockResponse = mock('RestClient::Response')
109
143
  mockResponse.stubs(:code).returns(200)
@@ -141,7 +175,7 @@ module Invoiced
141
175
  assert_equal('/customers/456/contacts/123', contact.endpoint())
142
176
  end
143
177
 
144
- should "list all of the customer's contact" do
178
+ should "list all of the customer's contacts" do
145
179
  mockResponse = mock('RestClient::Response')
146
180
  mockResponse.stubs(:code).returns(200)
147
181
  mockResponse.stubs(:body).returns('[{"id":123,"name":"Nancy"}]')
@@ -246,5 +280,70 @@ module Invoiced
246
280
  assert_instance_of(Invoiced::Invoice, invoice)
247
281
  assert_equal(4567, invoice.id)
248
282
  end
283
+
284
+ should "list all the customer's notes" do
285
+ mockResponse = mock('RestClient::Response')
286
+ mockResponse.stubs(:code).returns(200)
287
+ mockResponse.stubs(:body).returns('[{"id":1212,"notes":"example"}]')
288
+ mockResponse.stubs(:headers).returns(:x_total_count => 15, :link => '<https://api.invoiced.com/customers/123/notes?per_page=25&page=1>; rel="self", <https://api.invoiced.com/customers/123/notes?per_page=25&page=1>; rel="first", <https://api.invoiced.com/customers/123/notes?per_page=25&page=1>; rel="last"')
289
+
290
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
291
+
292
+ customer = Customer.new(@client, 123)
293
+ notes, metadata = customer.list_notes.list
294
+
295
+ assert_instance_of(Array, notes)
296
+ assert_equal(1, notes.length)
297
+ assert_equal(1212, notes[0].id)
298
+ assert_equal('/customers/123/notes/1212', notes[0].endpoint())
299
+
300
+ assert_instance_of(Invoiced::List, metadata)
301
+ assert_equal(15, metadata.total_count)
302
+ end
303
+
304
+ should "create a consolidated invoice" do
305
+ mockResponse = mock('RestClient::Response')
306
+ mockResponse.stubs(:code).returns(201)
307
+ mockResponse.stubs(:body).returns('{"id": 999,"total":1000}')
308
+ mockResponse.stubs(:headers).returns({})
309
+
310
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
311
+
312
+ customer = Customer.new(@client, 123)
313
+ invoice = customer.consolidate_invoices
314
+
315
+ assert_instance_of(Invoiced::Invoice, invoice)
316
+ assert_equal(invoice.id, 999)
317
+ end
318
+
319
+ should "create a bank account associated with customer" do
320
+ mockResponse = mock('RestClient::Response')
321
+ mockResponse.stubs(:code).returns(201)
322
+ mockResponse.stubs(:body).returns('{"id": 999,"object":"bank_account"}')
323
+ mockResponse.stubs(:headers).returns({})
324
+
325
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
326
+
327
+ customer = Customer.new(@client, 123)
328
+ account = customer.payment_sources.create
329
+
330
+ assert_instance_of(Invoiced::BankAccount, account)
331
+ assert_equal(account.endpoint, "/customers/123/bank_accounts/999")
332
+ end
333
+
334
+ should "create a card associated with customer" do
335
+ mockResponse = mock('RestClient::Response')
336
+ mockResponse.stubs(:code).returns(201)
337
+ mockResponse.stubs(:body).returns('{"id": 888,"object":"card"}')
338
+ mockResponse.stubs(:headers).returns({})
339
+
340
+ RestClient::Request.any_instance.expects(:execute).returns(mockResponse)
341
+
342
+ customer = Customer.new(@client, 123)
343
+ card = customer.payment_sources.create
344
+
345
+ assert_instance_of(Invoiced::Card, card)
346
+ assert_equal(card.endpoint, "/customers/123/cards/888")
347
+ end
249
348
  end
250
349
  end