harvested 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9671d7604da7b9da9bee9fd922b00cac9aa08a9
4
- data.tar.gz: e0295ab8a592616dff967a03a43ec9b0c669d3b9
3
+ metadata.gz: b320e8b059c090f49100d56dd033bd1cd8d388ea
4
+ data.tar.gz: 4edae05dec9b1f29e4e73315d071f104849b0911
5
5
  SHA512:
6
- metadata.gz: 5fac81456746627a0ff7372defcf6013ada70ae07e53013085c7844761b1a853c9f1f666af0d0fcdd3a83969a3b7d78c01b6b1ca499980e089301d2d5c56c154
7
- data.tar.gz: d54e0f9f6b67aa16747cf2f527d954a5bdc42501819727396b43a2abb0a4d53423940d85e0ea5b5378b2c501e02e800e4a895090c8890460c2bcce3b0c75f581
6
+ metadata.gz: 237ff0b0bd1c19bbd60620b9c4df92c2de856e3557c70e0a777a482f03bf5b5dfb9730668a88614664dfcebd5eef1ceb0363ca65397fa061c3c4f6d384ece125
7
+ data.tar.gz: 7956415b92ee623735f3eef012a74f0bc9ba039eee99eb66fdaf54a875356c5f28e2aac660b28bf300d2c7e5446a9e8c0ae709dc40bfed67e12438ed3c9664db
data/HISTORY.md CHANGED
@@ -1,10 +1,15 @@
1
+ ## 3.1.0 - Aug 29, 2014
2
+ * Allows Invoice Messages to be created (Thanks Thomas Balthazar - @tbalthazar)
3
+
4
+ ## 3.0.0 - Aug 29, 2014
5
+ * No longer requires Hashie v1 as a dependency
6
+ * Fixes bug where project hints were not handled properly
7
+
1
8
  ## 3.0.0.rc1 - May 30, 2014
2
9
  * Require Ruby 2.0+
3
10
  * Allow OAuth authentication (Thanks Brendan Loudermilk - @bloudermilk)
4
11
  * Allow expenses_by_project to be retrieved (Thanks Jordan Yeo - @jordanyeo)
5
12
  * Reports now pass through any remaining options (Thanks Philip Arndt - @parndt)
6
- * No longer requires Hashie v1 as a dependency
7
- * Fixes bug where project hints were not handled properly
8
13
 
9
14
  ## 2.0.0 - April 23, 2014
10
15
  * Every connection must be SSL
@@ -0,0 +1,75 @@
1
+ module Harvest
2
+ module API
3
+ class InvoiceMessages < Base
4
+ api_model Harvest::InvoiceMessage
5
+ include Harvest::Behavior::Crud
6
+
7
+ def all(invoice)
8
+ response = request(:get, credentials, "/invoices/#{invoice.to_i}/messages")
9
+ api_model.parse(response.parsed_response)
10
+ end
11
+
12
+ def find(invoice, message)
13
+ response = request(:get, credentials, "/invoices/#{invoice.to_i}/messages/#{message.to_i}")
14
+ api_model.parse(response.parsed_response).first
15
+ end
16
+
17
+ def create(message)
18
+ message = api_model.wrap(message)
19
+ response = request(:post, credentials, "/invoices/#{message.invoice_id}/messages", :body => message.to_json)
20
+ id = response.headers["location"].match(/\/.*\/(\d+)\/.*\/(\d+)/)[2]
21
+ find(message.invoice_id, id)
22
+ end
23
+
24
+ def delete(message)
25
+ request(:delete, credentials, "/invoices/#{message.invoice_id}/messages/#{message.to_i}")
26
+ message.id
27
+ end
28
+
29
+ # Create a message for marking an invoice as sent.
30
+ #
31
+ # @param [Harvest::InvoiceMessage] The message you want to send
32
+ # @return [Harvest::InvoiceMessage] The sent message
33
+ def mark_as_sent(message)
34
+ send_status_message(message, 'mark_as_sent')
35
+ end
36
+
37
+ # Create a message and mark an open invoice as closed (writing an invoice off)
38
+ #
39
+ # @param [Harvest::InvoiceMessage] The message you want to send
40
+ # @return [Harvest::InvoiceMessage] The sent message
41
+ def mark_as_closed(message)
42
+ send_status_message(message, 'mark_as_closed')
43
+ end
44
+
45
+ # Create a message and mark a closed (written-off) invoice as open
46
+ #
47
+ # @param [Harvest::InvoiceMessage] The message you want to send
48
+ # @return [Harvest::InvoiceMessage] The sent message
49
+ def re_open(message)
50
+ send_status_message(message, 're_open')
51
+ end
52
+
53
+ # Create a message for marking an open invoice as draft
54
+ #
55
+ # @param [Harvest::InvoiceMessage] The message you want to send
56
+ # @return [Harvest::InvoiceMessage] The sent message
57
+ def mark_as_draft(message)
58
+ send_status_message(message, 'mark_as_draft')
59
+ end
60
+
61
+ private
62
+
63
+ def send_status_message(message, action)
64
+ message = api_model.wrap(message)
65
+ response = request( :post,
66
+ credentials,
67
+ "/invoices/#{message.invoice_id}/messages/#{action}",
68
+ :body => message.to_json
69
+ )
70
+ message
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -288,5 +288,40 @@ module Harvest
288
288
  def invoice_payments
289
289
  @invoice_payments ||= Harvest::API::InvoicePayments.new(credentials)
290
290
  end
291
+
292
+ # All API Actions surrounding invoice messages
293
+ #
294
+ # == Examples
295
+ #
296
+ # invoice = harvest.invoices.find(100)
297
+ # harvest.invoice_messages.all(invoice) # returns all messages for the invoice (as Harvest::InvoicePayment)
298
+ #
299
+ # invoice = harvest.invoices.find(100)
300
+ # harvest.invoice_messages.find(invoice, 5) # returns the message with ID 5, assigned to the invoice
301
+ #
302
+ # invoice = harvest.invoices.find(100)
303
+ # message = Harvest::InvoiceMessage.new(:invoice_id => invoice.id)
304
+ # saved_message = harvest.invoice_messages.create(message) # returns a saved version of the message
305
+ #
306
+ # invoice = harvest.invoices.find(100)
307
+ # message = harvest.invoice_messages.find(invoice, 5)
308
+ # harvest.invoice_messages.delete(message) # returns 5
309
+ #
310
+ # invoice = harvest.invoices.find(100)
311
+ # message = Harvest::InvoiceMessage.new(:invoice_id => invoice.id)
312
+ # harvest.invoice_messages.mark_as_sent(message)
313
+ #
314
+ # invoice = harvest.invoices.find(100)
315
+ # message = Harvest::InvoiceMessage.new(:invoice_id => invoice.id)
316
+ # harvest.invoice_messages.mark_as_closed(message)
317
+ #
318
+ # invoice = harvest.invoices.find(100)
319
+ # message = Harvest::InvoiceMessage.new(:invoice_id => invoice.id)
320
+ # harvest.invoice_messages.re_open(message)
321
+ #
322
+ # @return [Harvest::API::InvoiceMessages]
323
+ def invoice_messages
324
+ @invoice_messages ||= Harvest::API::InvoiceMessages.new(credentials)
325
+ end
291
326
  end
292
327
  end
@@ -0,0 +1,8 @@
1
+ module Harvest
2
+ class InvoiceMessage < Hashie::Mash
3
+ include Harvest::Model
4
+
5
+ api_path '/messages'
6
+ def self.json_root; 'message'; end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Harvest
2
- VERSION = "3.0.0"
2
+ VERSION = "3.1.0"
3
3
  end
@@ -20,8 +20,8 @@ require 'harvest/timezones'
20
20
  require 'harvest/base'
21
21
 
22
22
  %w(crud activatable).each {|a| require "harvest/behavior/#{a}"}
23
- %w(model client contact project task user rate_limit_status task_assignment user_assignment expense_category expense time_entry invoice_category line_item invoice invoice_payment trackable_project).each {|a| require "harvest/#{a}"}
24
- %w(base account clients contacts projects tasks users task_assignments user_assignments expense_categories expenses time reports invoice_categories invoices invoice_payments).each {|a| require "harvest/api/#{a}"}
23
+ %w(model client contact project task user rate_limit_status task_assignment user_assignment expense_category expense time_entry invoice_category line_item invoice invoice_payment invoice_message trackable_project).each {|a| require "harvest/#{a}"}
24
+ %w(base account clients contacts projects tasks users task_assignments user_assignments expense_categories expenses time reports invoice_categories invoices invoice_payments invoice_messages).each {|a| require "harvest/api/#{a}"}
25
25
 
26
26
  module Harvest
27
27
  class << self
@@ -51,6 +51,14 @@ FactoryGirl.define do
51
51
  notes "Payment received"
52
52
  end
53
53
 
54
+ factory :invoice_message, class: Harvest::InvoiceMessage do
55
+ body "The message body goes here"
56
+ recipients "john@example.com, jane@example.com"
57
+ attach_pdf true
58
+ send_me_a_copy true
59
+ include_pay_pal_link true
60
+ end
61
+
54
62
  factory :project, class: Harvest::Project do
55
63
  name { generate(:project_name) }
56
64
  end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'harvest invoice messages' do
4
+ it 'allows adding/removing messages to invoice and retrieving existing invoice messages' do
5
+ # Make sure Reminder Message is turned off for this test to pass
6
+
7
+ cassette('invoice_message1') do
8
+ # create a new client and invoice
9
+ client = harvest.clients.create(FactoryGirl.attributes_for(:client))
10
+ invoice = harvest.invoices.create(FactoryGirl.attributes_for(:invoice, :client_id => client.id, :issued_at => Date.today - 2, :due_at_human_format => 'NET 30'))
11
+
12
+ # add a message to the invoice
13
+ message = Harvest::InvoiceMessage.new(FactoryGirl.attributes_for(:invoice_message,
14
+ :invoice_id => invoice.id,
15
+ :body => "A message body"))
16
+ message_saved = harvest.invoice_messages.create(message)
17
+
18
+ # retrieve the created invoice and compare
19
+ message_found = harvest.invoice_messages.find(invoice, message_saved)
20
+ message_found.should == message_saved
21
+
22
+ # add another message to the invoice
23
+ message2 = Harvest::InvoiceMessage.new(FactoryGirl.attributes_for(:invoice_message,
24
+ :invoice_id => invoice.id,
25
+ :body => "Another message body"))
26
+ message2_saved = harvest.invoice_messages.create(message2)
27
+
28
+ # get all the messages and test if our 2 saved messages are included
29
+ messages = harvest.invoice_messages.all(invoice)
30
+ messages.should include(message_saved)
31
+ messages.should include(message2_saved)
32
+
33
+ # remove a message
34
+ harvest.invoice_messages.delete(message_saved)
35
+ messages = harvest.invoice_messages.all(invoice)
36
+ messages.should_not include(message_saved)
37
+ messages.should include(message2_saved)
38
+
39
+ # remove another message
40
+ harvest.invoice_messages.delete(message2_saved)
41
+ messages = harvest.invoice_messages.all(invoice)
42
+ messages.should_not include(message_saved)
43
+ messages.should_not include(message2_saved)
44
+
45
+ harvest.invoice_messages.all(invoice).should be_empty
46
+ end
47
+ end
48
+
49
+ it 'allows to change the state of an invoice' do
50
+ cassette('invoice_message2') do
51
+ # create a new client and invoice
52
+ client = harvest.clients.create(FactoryGirl.attributes_for(:client))
53
+ invoice = harvest.invoices.create(FactoryGirl.attributes_for(:invoice, :client_id => client.id))
54
+
55
+ # check the invoice state is 'draft'
56
+ invoice = harvest.invoices.find(invoice.id)
57
+ invoice.state.should == 'draft'
58
+
59
+ # -- mark as sent
60
+ message = Harvest::InvoiceMessage.new(FactoryGirl.attributes_for(:invoice_message,
61
+ :invoice_id => invoice.id,
62
+ :body => "sent body message"))
63
+ harvest.invoice_messages.mark_as_sent(message)
64
+
65
+ # check the invoice state and latest message body
66
+ invoice = harvest.invoices.find(invoice.id)
67
+ invoice.state.should == 'open'
68
+ messages = harvest.invoice_messages.all(invoice)
69
+ messages.last.body.should == message.body
70
+
71
+ # -- mark_as_closed (write off)
72
+ message.body = "close body message"
73
+ harvest.invoice_messages.mark_as_closed(message)
74
+
75
+ # check the invoice state and latest message body
76
+ invoice = harvest.invoices.find(invoice.id)
77
+ invoice.state.should == 'closed'
78
+
79
+ # -- re_open
80
+ message.body = "re-open body message"
81
+ harvest.invoice_messages.re_open(message)
82
+ messages = harvest.invoice_messages.all(invoice)
83
+
84
+ # check the invoice state and latest message body
85
+ invoice = harvest.invoices.find(invoice.id)
86
+ invoice.state.should == 'open'
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::InvoiceMessage do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harvested
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Moazeni
@@ -87,6 +87,7 @@ files:
87
87
  - lib/harvest/api/expense_categories.rb
88
88
  - lib/harvest/api/expenses.rb
89
89
  - lib/harvest/api/invoice_categories.rb
90
+ - lib/harvest/api/invoice_messages.rb
90
91
  - lib/harvest/api/invoice_payments.rb
91
92
  - lib/harvest/api/invoices.rb
92
93
  - lib/harvest/api/projects.rb
@@ -108,6 +109,7 @@ files:
108
109
  - lib/harvest/hardy_client.rb
109
110
  - lib/harvest/invoice.rb
110
111
  - lib/harvest/invoice_category.rb
112
+ - lib/harvest/invoice_message.rb
111
113
  - lib/harvest/invoice_payment.rb
112
114
  - lib/harvest/line_item.rb
113
115
  - lib/harvest/model.rb
@@ -128,6 +130,7 @@ files:
128
130
  - spec/functional/errors_spec.rb
129
131
  - spec/functional/expenses_spec.rb
130
132
  - spec/functional/hardy_client_spec.rb
133
+ - spec/functional/invoice_messages_spec.rb
131
134
  - spec/functional/invoice_payments_spec.rb
132
135
  - spec/functional/invoice_spec.rb
133
136
  - spec/functional/project_spec.rb
@@ -139,6 +142,7 @@ files:
139
142
  - spec/harvest/basic_auth_credentials_spec.rb
140
143
  - spec/harvest/expense_category_spec.rb
141
144
  - spec/harvest/expense_spec.rb
145
+ - spec/harvest/invoice_message_spec.rb
142
146
  - spec/harvest/invoice_payment_spec.rb
143
147
  - spec/harvest/invoice_spec.rb
144
148
  - spec/harvest/oauth_credentials_spec.rb
@@ -184,6 +188,7 @@ test_files:
184
188
  - spec/functional/errors_spec.rb
185
189
  - spec/functional/expenses_spec.rb
186
190
  - spec/functional/hardy_client_spec.rb
191
+ - spec/functional/invoice_messages_spec.rb
187
192
  - spec/functional/invoice_payments_spec.rb
188
193
  - spec/functional/invoice_spec.rb
189
194
  - spec/functional/project_spec.rb
@@ -195,6 +200,7 @@ test_files:
195
200
  - spec/harvest/basic_auth_credentials_spec.rb
196
201
  - spec/harvest/expense_category_spec.rb
197
202
  - spec/harvest/expense_spec.rb
203
+ - spec/harvest/invoice_message_spec.rb
198
204
  - spec/harvest/invoice_payment_spec.rb
199
205
  - spec/harvest/invoice_spec.rb
200
206
  - spec/harvest/oauth_credentials_spec.rb