From 781a7affe91df19ef92f740cbc07f6c2014b20a3 Mon Sep 17 00:00:00 2001 From: Murray Summers Date: Sun, 2 Sep 2012 00:13:03 +0100 Subject: [PATCH 01/25] Create wrapper methods for oauth flow to prevent users directly accessing client and to make code cleaner in applications. --- lib/freeagent.rb | 16 ++++++++++++++++ lib/freeagent/client.rb | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/freeagent.rb b/lib/freeagent.rb index f5ce9e3..b8cc5fa 100644 --- a/lib/freeagent.rb +++ b/lib/freeagent.rb @@ -28,5 +28,21 @@ def access_details(client_id, client_secret, access_token=nil) @client = Client.new(client_id, client_secret) @client.access_token = access_token if access_token end + + def authorize(options) + @client.authorize(options) + end + + def fetch_access_token(auth_token, options) + @client.fetch_access_token(auth_token, options) + end + + def access_token=(access_token) + @client.access_token = access_token + end + + def access_token + @client.access_token.token + end end end diff --git a/lib/freeagent/client.rb b/lib/freeagent/client.rb index 05e2291..aa199c4 100644 --- a/lib/freeagent/client.rb +++ b/lib/freeagent/client.rb @@ -41,6 +41,14 @@ def self.token_url def self.connection_opts { :headers => { :user_agent => "freeagent-api-rb", :accept => "application/json", :content_type => "application/json" } } end + + def authorize(options) + if options[:redirect_uri] + @client.auth_code.authorize_url(options) + else + raise FreeAgent::ClientError.new('Redirect uri not specified') + end + end def fetch_access_token(auth_code, options) if options[:redirect_uri] From 399575dd7243929572cdcbd6a6e6725666ed8bc1 Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Wed, 15 May 2013 14:47:20 +0100 Subject: [PATCH 02/25] Fixed invoice view filters --- lib/freeagent/invoice.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index 5e35924..7117c11 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -22,27 +22,27 @@ def self.recent_open_or_overdue end def self.open_or_overdue - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => 'open_or_overdue') end def self.draft - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => 'draft') end def self.scheduled_to_email - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => 'scheduled_to_email') end def self.thank_you_emails - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => 'thank_you_emails') end def self.reminder_emails - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => 'reminder_emails') end def self.last_month(n) - Invoice.filter(:view => 'recent_open_or_overdue') + Invoice.filter(:view => "last_#{n}_months") end def self.find_all_by_contact(contact) From 27b32033eb59b17c2350935cb6af1e64d8d84e88 Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Tue, 23 Jul 2013 17:51:59 +0100 Subject: [PATCH 03/25] Added billing_email field to contact --- lib/freeagent/contact.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/contact.rb b/lib/freeagent/contact.rb index bba6637..28d4052 100644 --- a/lib/freeagent/contact.rb +++ b/lib/freeagent/contact.rb @@ -6,7 +6,7 @@ class Contact < Resource attr_accessor :first_name, :last_name, :contact_name_on_invoice, :country, :locale, :sales_tax_registration_number, :uses_contact_invoice_sequence - attr_accessor :organisation_name, :email, :phone_number + attr_accessor :organisation_name, :email, :billing_email, :phone_number attr_accessor :address1, :town, :region, :postcode, :address2, :address3, :country From cda4c126b752a4a203d7a0a7b2ed223d9788fdb9 Mon Sep 17 00:00:00 2001 From: John Knott Date: Wed, 24 Jul 2013 13:28:06 +0100 Subject: [PATCH 04/25] Made resource.save work like resource.create (return the object and throw exceptions instead of returning true/false) so that we can get IDs back on new records --- lib/freeagent/resource.rb | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/freeagent/resource.rb b/lib/freeagent/resource.rb index 1e33c8b..f107d2e 100644 --- a/lib/freeagent/resource.rb +++ b/lib/freeagent/resource.rb @@ -28,17 +28,17 @@ def inspect vars = to_hash.collect { |k,v| "#{k}=#{v.inspect}" } "#<#{self.class}: #{vars.join(', ')}>" end - + def to_hash hash = {} instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var) } hash end - + def to_json MultiJson.encode(to_hash) end - + class << self attr_accessor :endpoint end @@ -64,7 +64,7 @@ def self.resource_methods(*args) define_delete if args.include? :delete end end - + def self.decimal_accessor(*args) decimal_reader(*args) decimal_writer(*args) @@ -123,7 +123,7 @@ def self.define_find response = FreeAgent.client.get("#{endpoint[:plural]}/#{id}") self.new(response[endpoint[:single]]) rescue FreeAgent::ApiError => error - raise error if FreeAgent.debug + raise error if FreeAgent.debug nil end end @@ -137,17 +137,14 @@ def self.define_create_and_save end define_method(:save) do - begin - data = { self.class.endpoint[:single].to_sym => self.to_hash } - if persisted? - FreeAgent.client.put("#{self.class.endpoint[:plural]}/#{id}", data) - else - FreeAgent.client.post(self.class.endpoint[:plural], data) - end - true - rescue FreeAgent::ApiError => error - false + data = { self.class.endpoint[:single].to_sym => self.to_hash } + response = nil + if persisted? + response = FreeAgent.client.put("#{self.class.endpoint[:plural]}/#{id}", data) + else + response = FreeAgent.client.post(self.class.endpoint[:plural], data) end + self.new(response[endpoint[:single]]) end end From d1efae6a446b1c3b9aaf136e7325904312b0fde0 Mon Sep 17 00:00:00 2001 From: John Knott Date: Wed, 24 Jul 2013 13:32:44 +0100 Subject: [PATCH 05/25] Fixed class method reference --- lib/freeagent/resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/resource.rb b/lib/freeagent/resource.rb index f107d2e..a17d855 100644 --- a/lib/freeagent/resource.rb +++ b/lib/freeagent/resource.rb @@ -144,7 +144,7 @@ def self.define_create_and_save else response = FreeAgent.client.post(self.class.endpoint[:plural], data) end - self.new(response[endpoint[:single]]) + self.new(response[self.class.endpoint[:single]]) end end From 1cd7e2c6f4a9f94c331fa12a41be3c05f892ea22 Mon Sep 17 00:00:00 2001 From: John Knott Date: Wed, 24 Jul 2013 13:37:44 +0100 Subject: [PATCH 06/25] Fixed class method reference --- lib/freeagent/resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/resource.rb b/lib/freeagent/resource.rb index a17d855..2d1cbd2 100644 --- a/lib/freeagent/resource.rb +++ b/lib/freeagent/resource.rb @@ -144,7 +144,7 @@ def self.define_create_and_save else response = FreeAgent.client.post(self.class.endpoint[:plural], data) end - self.new(response[self.class.endpoint[:single]]) + self.class.new(response[self.class.endpoint[:single]]) end end From faf65ad47a81580d2522224a0489ea2e6b1edacb Mon Sep 17 00:00:00 2001 From: John Knott Date: Thu, 1 Aug 2013 11:17:06 +0100 Subject: [PATCH 07/25] fa resource fix --- lib/freeagent/resource.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/freeagent/resource.rb b/lib/freeagent/resource.rb index 2d1cbd2..1f82524 100644 --- a/lib/freeagent/resource.rb +++ b/lib/freeagent/resource.rb @@ -144,6 +144,7 @@ def self.define_create_and_save else response = FreeAgent.client.post(self.class.endpoint[:plural], data) end + response = FreeAgent.client.get("#{self.class.endpoint[:plural]}/#{id}") self.class.new(response[self.class.endpoint[:single]]) end end From afe94a4e0b78cb5edfac09cedaba5871f98f537e Mon Sep 17 00:00:00 2001 From: John Knott Date: Thu, 1 Aug 2013 17:11:25 +0100 Subject: [PATCH 08/25] fix --- lib/freeagent/resource.rb | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/freeagent/resource.rb b/lib/freeagent/resource.rb index 1f82524..6140174 100644 --- a/lib/freeagent/resource.rb +++ b/lib/freeagent/resource.rb @@ -136,17 +136,18 @@ def self.define_create_and_save self.new(response[endpoint[:single]]) end - define_method(:save) do - data = { self.class.endpoint[:single].to_sym => self.to_hash } - response = nil - if persisted? - response = FreeAgent.client.put("#{self.class.endpoint[:plural]}/#{id}", data) - else - response = FreeAgent.client.post(self.class.endpoint[:plural], data) - end - response = FreeAgent.client.get("#{self.class.endpoint[:plural]}/#{id}") - self.class.new(response[self.class.endpoint[:single]]) + define_method(:save) do + data = { self.class.endpoint[:single].to_sym => self.to_hash } + response = nil + if persisted? + response = FreeAgent.client.put("#{self.class.endpoint[:plural]}/#{id}", data) + response = FreeAgent.client.get("#{self.class.endpoint[:plural]}/#{id}") + else + response = FreeAgent.client.post(self.class.endpoint[:plural], data) + end + self.class.new(response[self.class.endpoint[:single]]) end + end def self.define_update From 8a778fb80db7d6d21d1443903649e147192e806d Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Tue, 20 Aug 2013 17:36:08 +0100 Subject: [PATCH 09/25] Clean up some RSpec deprecations --- spec/client_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/client_spec.rb b/spec/client_spec.rb index a5f5621..a28c9d9 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -9,9 +9,9 @@ end it 'should raise client error when no client id or secret specified' do - expect { FreeAgent::Client.new(nil, '') }.should raise_error(FreeAgent::ClientError) - expect { FreeAgent::Client.new('', nil) }.should raise_error(FreeAgent::ClientError) - expect { FreeAgent::Client.new(nil, nil) }.should raise_error(FreeAgent::ClientError) + expect { FreeAgent::Client.new(nil, '') }.to raise_error(FreeAgent::ClientError) + expect { FreeAgent::Client.new('', nil) }.to raise_error(FreeAgent::ClientError) + expect { FreeAgent::Client.new(nil, nil) }.to raise_error(FreeAgent::ClientError) end end @@ -114,7 +114,7 @@ it 'should raise client error when redirect not specified' do fetch_access_token = expect {@client.fetch_access_token('auth_code', {})} - fetch_access_token.should raise_error(FreeAgent::ClientError) + fetch_access_token.to raise_error(FreeAgent::ClientError) end end From e1b084417d8e7350dfa992add5f986a7e55e88d4 Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Wed, 21 Aug 2013 10:14:13 +0100 Subject: [PATCH 10/25] Added methods to follow REST href's in Timeslip. Need a better way to do this all over. --- lib/freeagent/timeslip.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/freeagent/timeslip.rb b/lib/freeagent/timeslip.rb index 8c89494..94d8ada 100644 --- a/lib/freeagent/timeslip.rb +++ b/lib/freeagent/timeslip.rb @@ -6,7 +6,19 @@ class Timeslip < Resource attr_accessor :user, :project, :task, :comment + def follow_user + FreeAgent::User.find(extract_id(@user)) + end + + def follow_project + FreeAgent::Project.find(extract_id(@project)) + end + + def follow_task + FreeAgent::Task.find(extract_id(@task)) + end + decimal_accessor :hours date_accessor :dated_on, :created_at, :updated_at end -end \ No newline at end of file +end From 050d83ae5e6311a8a0d869f26ce1998fd696b3b4 Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Tue, 27 Aug 2013 14:09:57 +0100 Subject: [PATCH 11/25] Accept a refresh_token and delegate refresh! calls to OAuth2 lib --- lib/freeagent.rb | 3 ++- lib/freeagent/client.rb | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/freeagent.rb b/lib/freeagent.rb index ba0fed7..f26092d 100644 --- a/lib/freeagent.rb +++ b/lib/freeagent.rb @@ -24,9 +24,10 @@ class << self attr_accessor :debug attr_reader :client - def access_details(client_id, client_secret, access_token=nil) + def access_details(client_id, client_secret, access_token=nil, refresh_token=nil) @client = Client.new(client_id, client_secret) @client.access_token = access_token if access_token + @client.refresh_token = refresh_token if refresh_token end def authorize(options) diff --git a/lib/freeagent/client.rb b/lib/freeagent/client.rb index aa199c4..b69afaa 100644 --- a/lib/freeagent/client.rb +++ b/lib/freeagent/client.rb @@ -49,7 +49,7 @@ def authorize(options) raise FreeAgent::ClientError.new('Redirect uri not specified') end end - + def fetch_access_token(auth_code, options) if options[:redirect_uri] @access_token = @client.auth_code.get_token(auth_code, options) @@ -66,6 +66,22 @@ def access_token=(token) @access_token = OAuth2::AccessToken.new(@client, token) end + def refresh_token + @access_token.try(:refresh_token) + end + + def refresh_token=(token) + if @access_token + @access_token.refresh_token = token + else + raise FreeAgent::ClientError.new('Access Token not specified') + end + end + + def refresh_access_token! + @access_token.refresh! + end + def get(path, params={}) request(:get, "#{Client.site}#{path}", :params => params).parsed end From 439d9c64e397e18be06ba89e01f8b09f75444e42 Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Tue, 27 Aug 2013 16:37:34 +0100 Subject: [PATCH 12/25] Allow initialization from a refresh_token or an access_token --- lib/freeagent.rb | 20 ++++---------------- lib/freeagent/client.rb | 19 ++++++++----------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/lib/freeagent.rb b/lib/freeagent.rb index f26092d..bbc9755 100644 --- a/lib/freeagent.rb +++ b/lib/freeagent.rb @@ -23,27 +23,15 @@ class << self attr_accessor :environment attr_accessor :debug attr_reader :client - - def access_details(client_id, client_secret, access_token=nil, refresh_token=nil) + + def access_details(client_id, client_secret, options=nil) @client = Client.new(client_id, client_secret) - @client.access_token = access_token if access_token - @client.refresh_token = refresh_token if refresh_token + @client.refresh_token = options[:refresh_token] if options[:refresh_token] + @client.access_token = options[:refresh_token] if options[:access_token] end def authorize(options) @client.authorize(options) end - - def fetch_access_token(auth_token, options) - @client.fetch_access_token(auth_token, options) - end - - def access_token=(access_token) - @client.access_token = access_token - end - - def access_token - @client.access_token.token - end end end diff --git a/lib/freeagent/client.rb b/lib/freeagent/client.rb index b69afaa..9ad28e8 100644 --- a/lib/freeagent/client.rb +++ b/lib/freeagent/client.rb @@ -70,16 +70,13 @@ def refresh_token @access_token.try(:refresh_token) end - def refresh_token=(token) - if @access_token - @access_token.refresh_token = token - else - raise FreeAgent::ClientError.new('Access Token not specified') - end - end - - def refresh_access_token! - @access_token.refresh! + def refresh_token=(refresh_token) + @access_token = OAuth2::AccessToken.new( + @client, + nil, + refresh_token: refresh_token + ) + @access_token = @access_token.refresh! end def get(path, params={}) @@ -98,7 +95,7 @@ def delete(path, data={}) request(:delete, "#{Client.site}#{path}", :data => data).parsed end - private + private def request(method, path, options = {}) if @access_token From 721397db81ff8b3f47828c4fecdc61d8c897507d Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Wed, 28 Aug 2013 11:10:25 +0100 Subject: [PATCH 13/25] Update dependencies --- Gemfile.lock | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 44127b6..ad6c2ff 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,33 +8,38 @@ PATH GEM remote: http://rubygems.org/ specs: - coderay (1.0.6) - diff-lcs (1.1.3) - faraday (0.8.0) - multipart-post (~> 1.1) - httpauth (0.1) - method_source (0.7.1) - multi_json (1.3.6) - multipart-post (1.1.5) - oauth2 (0.7.1) + coderay (1.0.9) + diff-lcs (1.2.4) + faraday (0.8.8) + multipart-post (~> 1.2.0) + httpauth (0.2.0) + jwt (0.1.8) + multi_json (>= 1.5) + method_source (0.8.2) + multi_json (1.7.9) + multi_xml (0.5.5) + multipart-post (1.2.0) + oauth2 (0.9.2) faraday (~> 0.8) - httpauth (~> 0.1) + httpauth (~> 0.2) + jwt (~> 0.1.4) multi_json (~> 1.0) - rack (~> 1.4) - pry (0.9.9.6) + multi_xml (~> 0.5) + rack (~> 1.2) + pry (0.9.12.2) coderay (~> 1.0.5) - method_source (~> 0.7.1) - slop (>= 2.4.4, < 3) - rack (1.4.1) - rspec (2.10.0) - rspec-core (~> 2.10.0) - rspec-expectations (~> 2.10.0) - rspec-mocks (~> 2.10.0) - rspec-core (2.10.0) - rspec-expectations (2.10.0) - diff-lcs (~> 1.1.3) - rspec-mocks (2.10.1) - slop (2.4.4) + method_source (~> 0.8) + slop (~> 3.4) + rack (1.5.2) + rspec (2.14.1) + rspec-core (~> 2.14.0) + rspec-expectations (~> 2.14.0) + rspec-mocks (~> 2.14.0) + rspec-core (2.14.5) + rspec-expectations (2.14.2) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.14.3) + slop (3.4.6) PLATFORMS ruby From e31cc6da72f344cdc7f5c47cc3232a986e3afd26 Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Wed, 28 Aug 2013 11:31:07 +0100 Subject: [PATCH 14/25] Remove Gemfile.lock --- Gemfile | 2 -- Gemfile.lock | 50 -------------------------------------------------- 2 files changed, 52 deletions(-) delete mode 100644 Gemfile.lock diff --git a/Gemfile b/Gemfile index df2e81c..66e32a6 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,3 @@ source "http://rubygems.org" # Specify gem dependencies in freeagent-api-ruby.gemspec gemspec - - diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index ad6c2ff..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,50 +0,0 @@ -PATH - remote: . - specs: - freeagent-api-ruby (0.0.1) - multi_json - oauth2 - -GEM - remote: http://rubygems.org/ - specs: - coderay (1.0.9) - diff-lcs (1.2.4) - faraday (0.8.8) - multipart-post (~> 1.2.0) - httpauth (0.2.0) - jwt (0.1.8) - multi_json (>= 1.5) - method_source (0.8.2) - multi_json (1.7.9) - multi_xml (0.5.5) - multipart-post (1.2.0) - oauth2 (0.9.2) - faraday (~> 0.8) - httpauth (~> 0.2) - jwt (~> 0.1.4) - multi_json (~> 1.0) - multi_xml (~> 0.5) - rack (~> 1.2) - pry (0.9.12.2) - coderay (~> 1.0.5) - method_source (~> 0.8) - slop (~> 3.4) - rack (1.5.2) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.5) - rspec-expectations (2.14.2) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.3) - slop (3.4.6) - -PLATFORMS - ruby - -DEPENDENCIES - freeagent-api-ruby! - pry - rspec From 81ec69a46bb4a6e65dc1e5800afa7ef4da9fc6ee Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Wed, 28 Aug 2013 11:41:54 +0100 Subject: [PATCH 15/25] Ignore Gemfile.lock and specify newer OAuth2 --- .gitignore | 2 ++ freeagent-api-ruby.gemspec | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b0302f2..0da7fad 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .rvmrc example.rb resource_list + +Gemfile.lock diff --git a/freeagent-api-ruby.gemspec b/freeagent-api-ruby.gemspec index 0e54e27..00273cf 100644 --- a/freeagent-api-ruby.gemspec +++ b/freeagent-api-ruby.gemspec @@ -15,11 +15,11 @@ Gem::Specification.new do |s| s.add_development_dependency "rspec" s.add_development_dependency "pry" - s.add_runtime_dependency "oauth2" + s.add_runtime_dependency "oauth2", "~> 0.9.2" s.add_runtime_dependency "multi_json" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] -end \ No newline at end of file +end From a6123f6a503caaf75553a5c9dbd67e0b32140c6a Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Sat, 31 Aug 2013 07:03:11 +0100 Subject: [PATCH 16/25] Added send method to invoice class --- lib/freeagent/invoice.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index 7117c11..af736f6 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -58,6 +58,18 @@ def self.find_all_by_project(project) # FreeAgent.client.post("invoices/#{id}/send_email", email) #end + def send(from, to, subject, msg) + FreeAgent.client.post("invoices/#{id}/send_email",{ + :invoice => { + :email => { + :to => to, + :from => from, + :subject => subject, + :body => msg + } + }}) + end + def mark_as_sent FreeAgent.client.put("invoices/#{id}/transitions/mark_as_sent", nil) end From 05e0012b5cfa0e2550a5fc30ea45e144a29d04dc Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Sat, 31 Aug 2013 07:26:32 +0100 Subject: [PATCH 17/25] Changed send method to send_email --- lib/freeagent/invoice.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index af736f6..4704a22 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -58,7 +58,7 @@ def self.find_all_by_project(project) # FreeAgent.client.post("invoices/#{id}/send_email", email) #end - def send(from, to, subject, msg) + def send_email(from, to, subject, msg) FreeAgent.client.post("invoices/#{id}/send_email",{ :invoice => { :email => { From d856e9e6b69bdb9cb01839f475f63a04d2f0560b Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Thu, 31 Oct 2013 14:47:56 +0000 Subject: [PATCH 18/25] Implemented automatic pagination for GET's Unless :auto_paginate => false --- lib/freeagent/client.rb | 45 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/freeagent/client.rb b/lib/freeagent/client.rb index 05e2291..17ea8c2 100644 --- a/lib/freeagent/client.rb +++ b/lib/freeagent/client.rb @@ -58,8 +58,37 @@ def access_token=(token) @access_token = OAuth2::AccessToken.new(@client, token) end + def get_default(params) + { + auto_paginate: true, + per_page: 100 + }.merge params + end + def get(path, params={}) - request(:get, "#{Client.site}#{path}", :params => params).parsed + response = request(:get, "#{Client.site}#{path}", :params => params) + params = get_default(params) + + if params[:auto_paginate] + auto_paginate(response, params) + else + response.parsed + end + end + + def auto_paginate(response, params) + rels = process_rels(response) + items = response.parsed + + while rels[:next] + response = request(:get, rels[:next], :params => params) + rels = process_rels(response) + items.merge response.parsed do |_, current, new| + current.concat new + end + end + + items end def post(path, data={}) @@ -76,6 +105,20 @@ def delete(path, data={}) private + # Finds link relations from 'Link' response header + # + # Returns an array of Relations + # https://github.com/lostisland/sawyer/blob/master/lib/sawyer/response.rb + def process_rels(response) + links = (response.headers["Link"] || "" ).split(', ').map do |link| + href, name = link.match(/<(.*?)>; rel=['"](\w+)["']/).captures + [name.to_sym, href] + end + + Hash[*links.flatten] + end + + def request(method, path, options = {}) if @access_token options[:body] = MultiJson.encode(options[:data]) unless options[:data].nil? From 4e58edb4168b83e53a8ef39b5c7be0de2245df6f Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Thu, 31 Oct 2013 14:45:59 +0000 Subject: [PATCH 19/25] Fixed bug when passing access_token --- lib/freeagent.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent.rb b/lib/freeagent.rb index bbc9755..2b137bc 100644 --- a/lib/freeagent.rb +++ b/lib/freeagent.rb @@ -27,7 +27,7 @@ class << self def access_details(client_id, client_secret, options=nil) @client = Client.new(client_id, client_secret) @client.refresh_token = options[:refresh_token] if options[:refresh_token] - @client.access_token = options[:refresh_token] if options[:access_token] + @client.access_token = options[:access_token] if options[:access_token] end def authorize(options) From c2130b0b18c93f9be06c7ca6cc71fa773f246f3e Mon Sep 17 00:00:00 2001 From: Joe Stanton Date: Thu, 31 Oct 2013 16:08:10 +0000 Subject: [PATCH 20/25] Merge params before initial request --- lib/freeagent/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/client.rb b/lib/freeagent/client.rb index 17ea8c2..c719724 100644 --- a/lib/freeagent/client.rb +++ b/lib/freeagent/client.rb @@ -66,8 +66,8 @@ def get_default(params) end def get(path, params={}) - response = request(:get, "#{Client.site}#{path}", :params => params) params = get_default(params) + response = request(:get, "#{Client.site}#{path}", :params => params) if params[:auto_paginate] auto_paginate(response, params) From 096695a5b0230726acc5958561bd6dd932fc87bc Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Wed, 13 Nov 2013 16:38:47 +0000 Subject: [PATCH 21/25] Gone back to old version of Oauth2 for dependancy reasons --- freeagent-api-ruby.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freeagent-api-ruby.gemspec b/freeagent-api-ruby.gemspec index 00273cf..fc1c6ec 100644 --- a/freeagent-api-ruby.gemspec +++ b/freeagent-api-ruby.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rspec" s.add_development_dependency "pry" - s.add_runtime_dependency "oauth2", "~> 0.9.2" + s.add_runtime_dependency "oauth2" s.add_runtime_dependency "multi_json" s.files = `git ls-files`.split("\n") From 3938f3c452d9dfc274a85708416f256f4f6061ac Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Wed, 13 Nov 2013 16:48:13 +0000 Subject: [PATCH 22/25] oAuth change --- lib/freeagent.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/freeagent.rb b/lib/freeagent.rb index 2b137bc..328c161 100644 --- a/lib/freeagent.rb +++ b/lib/freeagent.rb @@ -24,10 +24,9 @@ class << self attr_accessor :debug attr_reader :client - def access_details(client_id, client_secret, options=nil) + def access_details(client_id, client_secret, access_token=nil) @client = Client.new(client_id, client_secret) - @client.refresh_token = options[:refresh_token] if options[:refresh_token] - @client.access_token = options[:access_token] if options[:access_token] + @client.access_token = access_token if access_token end def authorize(options) From c37f5c1e7c380a21c22d271e4f1bf775dbb15ca4 Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Fri, 9 Jan 2015 17:30:16 +0000 Subject: [PATCH 23/25] Added paid_on to invoices so we can obtain invoice paid date --- lib/freeagent/invoice.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index 4704a22..541a233 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -10,7 +10,7 @@ class Invoice < Resource decimal_accessor :exchange_rate, :net_value, :sales_tax_value - date_accessor :dated_on, :due_on + date_accessor :dated_on, :due_on, :paid_on # TODO FIXME Need to rename this better def self.all_with_nested_items From ecb2501c07bbdbb4aadc0a29cf3efcfd9dd70fb3 Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Mon, 18 Apr 2016 15:13:25 +0100 Subject: [PATCH 24/25] Added place_of_supply for VAT Moss --- lib/freeagent/invoice.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index 541a233..9d44274 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -4,7 +4,7 @@ class Invoice < Resource resource_methods :default - attr_accessor :contact, :reference, :currency, :status, :omit_header, :payment_terms_in_days, :ec_status, :invoice_items + attr_accessor :contact, :reference, :currency, :status, :omit_header, :payment_terms_in_days, :ec_status, :place_of_supply, :invoice_items attr_accessor :project, :discount_percent, :written_off_date @@ -87,4 +87,4 @@ def mark_as_cancelled # #end end -end \ No newline at end of file +end From 105d98b476c149b59478e170b1aec97808b68ded Mon Sep 17 00:00:00 2001 From: Simon Moxon Date: Mon, 5 Sep 2016 09:39:12 +0100 Subject: [PATCH 25/25] Added delete_invoice method to invoices --- lib/freeagent/invoice.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/freeagent/invoice.rb b/lib/freeagent/invoice.rb index 9d44274..d217dba 100644 --- a/lib/freeagent/invoice.rb +++ b/lib/freeagent/invoice.rb @@ -81,6 +81,10 @@ def mark_as_draft def mark_as_cancelled FreeAgent.client.put("invoices/#{id}/transitions/mark_as_cancelled", nil) end + + def delete_invoice + FreeAgent.client.delete("invoices/#{id}") + end # TODO Write invoice timeline wrapper #def timeline