harvested 3.0.0 → 3.1.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.
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