invoiced 0.12.0 → 1.2.0

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