freeagentrb 0.1.0 → 0.1.2
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 +4 -4
- data/.rubocop.yml +11 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +91 -33
- data/Rakefile +9 -3
- data/freeagentrb.gemspec +7 -10
- data/lib/free_agent/client.rb +9 -4
- data/lib/free_agent/collection.rb +28 -9
- data/lib/free_agent/error_generator.rb +137 -0
- data/lib/free_agent/object.rb +2 -2
- data/lib/free_agent/objects/bank_transaction.rb +17 -0
- data/lib/free_agent/objects/category.rb +4 -0
- data/lib/free_agent/objects/invoice.rb +9 -0
- data/lib/free_agent/resource.rb +14 -26
- data/lib/free_agent/resources/attachments.rb +0 -2
- data/lib/free_agent/resources/bank_accounts.rb +2 -4
- data/lib/free_agent/resources/bank_transaction_explanations.rb +7 -10
- data/lib/free_agent/resources/bank_transactions.rb +4 -6
- data/lib/free_agent/resources/bills.rb +6 -8
- data/lib/free_agent/resources/categories.rb +18 -0
- data/lib/free_agent/resources/company.rb +0 -2
- data/lib/free_agent/resources/contacts.rb +1 -3
- data/lib/free_agent/resources/credit_notes.rb +8 -10
- data/lib/free_agent/resources/estimate_items.rb +1 -3
- data/lib/free_agent/resources/estimates.rb +8 -10
- data/lib/free_agent/resources/invoices.rb +8 -10
- data/lib/free_agent/resources/projects.rb +3 -5
- data/lib/free_agent/resources/tasks.rb +3 -5
- data/lib/free_agent/resources/timeslips.rb +5 -7
- data/lib/free_agent/resources/users.rb +3 -5
- data/lib/free_agent/version.rb +1 -1
- data/lib/free_agent.rb +6 -2
- data/lib/freeagentrb.rb +1 -1
- metadata +12 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 88898202cc7b4ac0e04002a27eadce03209e346b6dfb923978957d5a3d2c5015
|
|
4
|
+
data.tar.gz: c09f7138b792427372c751aee5ab7b26150ed6788d3dc7017bd9d1e4c2401d78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13a89e9d1296d6a4c92aa46b66a2fbd50b08fc603a6a5a3b5bfb5d5e00d82764018b52a07d8f8f9cb1982e33ace2af110ed7213cb59380e8072205994349a886
|
|
7
|
+
data.tar.gz: 25434579eaf40d09120e248aea740a947fff670ca08a7e72ab48f45888211034b1503956bf1335525234b133663180a44035d9030b88ac5dbe29b51fccd83c8e
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Omakase Ruby styling for Rails
|
|
2
|
+
inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
|
3
|
+
|
|
4
|
+
# Overwrite or add rules to create your own house style
|
|
5
|
+
#
|
|
6
|
+
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
|
|
7
|
+
# Layout/SpaceInsideArrayLiteralBrackets:
|
|
8
|
+
# Enabled: false
|
|
9
|
+
|
|
10
|
+
Rails/RefuteMethods:
|
|
11
|
+
Enabled: false
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,43 +1,98 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
freeagentrb (0.1.
|
|
5
|
-
faraday (~>
|
|
4
|
+
freeagentrb (0.1.2)
|
|
5
|
+
faraday (~> 2.11)
|
|
6
6
|
faraday-multipart (~> 1.0)
|
|
7
|
-
faraday_middleware (~> 1.1)
|
|
8
7
|
|
|
9
8
|
GEM
|
|
10
9
|
remote: https://rubygems.org/
|
|
11
10
|
specs:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
faraday
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
11
|
+
activesupport (8.0.1)
|
|
12
|
+
base64
|
|
13
|
+
benchmark (>= 0.3)
|
|
14
|
+
bigdecimal
|
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
16
|
+
connection_pool (>= 2.2.5)
|
|
17
|
+
drb
|
|
18
|
+
i18n (>= 1.6, < 2)
|
|
19
|
+
logger (>= 1.4.2)
|
|
20
|
+
minitest (>= 5.1)
|
|
21
|
+
securerandom (>= 0.3)
|
|
22
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
23
|
+
uri (>= 0.13.1)
|
|
24
|
+
ast (2.4.2)
|
|
25
|
+
base64 (0.2.0)
|
|
26
|
+
benchmark (0.4.0)
|
|
27
|
+
bigdecimal (3.1.9)
|
|
28
|
+
concurrent-ruby (1.3.5)
|
|
29
|
+
connection_pool (2.5.0)
|
|
30
|
+
dotenv (3.1.7)
|
|
31
|
+
drb (2.2.1)
|
|
32
|
+
faraday (2.12.2)
|
|
33
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
34
|
+
json
|
|
35
|
+
logger
|
|
36
|
+
faraday-multipart (1.1.0)
|
|
37
|
+
multipart-post (~> 2.0)
|
|
38
|
+
faraday-net_http (3.4.0)
|
|
39
|
+
net-http (>= 0.5.0)
|
|
40
|
+
i18n (1.14.7)
|
|
41
|
+
concurrent-ruby (~> 1.0)
|
|
42
|
+
json (2.9.1)
|
|
43
|
+
language_server-protocol (3.17.0.4)
|
|
44
|
+
logger (1.6.5)
|
|
45
|
+
minitest (5.25.4)
|
|
46
|
+
multipart-post (2.4.1)
|
|
47
|
+
net-http (0.6.0)
|
|
48
|
+
uri
|
|
49
|
+
parallel (1.26.3)
|
|
50
|
+
parser (3.3.7.0)
|
|
51
|
+
ast (~> 2.4.1)
|
|
52
|
+
racc
|
|
53
|
+
racc (1.8.1)
|
|
54
|
+
rack (3.1.8)
|
|
55
|
+
rainbow (3.1.1)
|
|
56
|
+
rake (13.2.1)
|
|
57
|
+
regexp_parser (2.10.0)
|
|
58
|
+
rubocop (1.71.0)
|
|
59
|
+
json (~> 2.3)
|
|
60
|
+
language_server-protocol (>= 3.17.0)
|
|
61
|
+
parallel (~> 1.10)
|
|
62
|
+
parser (>= 3.3.0.2)
|
|
63
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
64
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
65
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
|
66
|
+
ruby-progressbar (~> 1.7)
|
|
67
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
68
|
+
rubocop-ast (1.38.0)
|
|
69
|
+
parser (>= 3.3.1.0)
|
|
70
|
+
rubocop-minitest (0.36.0)
|
|
71
|
+
rubocop (>= 1.61, < 2.0)
|
|
72
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
|
73
|
+
rubocop-performance (1.23.1)
|
|
74
|
+
rubocop (>= 1.48.1, < 2.0)
|
|
75
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
|
76
|
+
rubocop-rails (2.29.1)
|
|
77
|
+
activesupport (>= 4.2.0)
|
|
78
|
+
rack (>= 1.1)
|
|
79
|
+
rubocop (>= 1.52.0, < 2.0)
|
|
80
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
|
81
|
+
rubocop-rails-omakase (1.0.0)
|
|
82
|
+
rubocop
|
|
83
|
+
rubocop-minitest
|
|
84
|
+
rubocop-performance
|
|
85
|
+
rubocop-rails
|
|
86
|
+
ruby-progressbar (1.13.0)
|
|
87
|
+
securerandom (0.4.1)
|
|
88
|
+
tzinfo (2.0.6)
|
|
89
|
+
concurrent-ruby (~> 1.0)
|
|
90
|
+
unicode-display_width (3.1.4)
|
|
91
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
92
|
+
unicode-emoji (4.0.4)
|
|
93
|
+
uri (1.0.2)
|
|
94
|
+
vcr (6.3.1)
|
|
95
|
+
base64
|
|
41
96
|
|
|
42
97
|
PLATFORMS
|
|
43
98
|
x86_64-linux
|
|
@@ -45,7 +100,10 @@ PLATFORMS
|
|
|
45
100
|
DEPENDENCIES
|
|
46
101
|
dotenv
|
|
47
102
|
freeagentrb!
|
|
103
|
+
minitest (~> 5.0)
|
|
48
104
|
rake (~> 13.0)
|
|
105
|
+
rubocop-rails-omakase
|
|
106
|
+
vcr
|
|
49
107
|
|
|
50
108
|
BUNDLED WITH
|
|
51
|
-
2.
|
|
109
|
+
2.6.3
|
data/Rakefile
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
require "bundler/gem_tasks"
|
|
4
|
-
|
|
2
|
+
require "rake/testtask"
|
|
3
|
+
|
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
|
5
|
+
t.libs << "test"
|
|
6
|
+
t.libs << "lib"
|
|
7
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
task default: :test
|
data/freeagentrb.gemspec
CHANGED
|
@@ -5,17 +5,17 @@ require_relative "lib/free_agent/version"
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "freeagentrb"
|
|
7
7
|
spec.version = FreeAgent::VERSION
|
|
8
|
-
spec.authors = ["Dean Perry"]
|
|
9
|
-
spec.email = ["dean@deanpcmad.com"]
|
|
8
|
+
spec.authors = [ "Dean Perry" ]
|
|
9
|
+
spec.email = [ "dean@deanpcmad.com" ]
|
|
10
10
|
|
|
11
|
-
spec.summary = "
|
|
11
|
+
spec.summary = "Ruby library for the FreeAgent v2 API"
|
|
12
12
|
spec.homepage = "https://deanpcmad.com"
|
|
13
|
+
|
|
13
14
|
spec.license = "MIT"
|
|
14
15
|
spec.required_ruby_version = ">= 2.6.0"
|
|
15
16
|
|
|
16
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
17
|
-
|
|
18
|
-
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/deanpcmad/freeagentrb"
|
|
19
19
|
|
|
20
20
|
# Specify which files should be added to the gem when it is released.
|
|
21
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
@@ -24,11 +24,8 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
|
-
spec.
|
|
28
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
29
|
-
spec.require_paths = ["lib"]
|
|
27
|
+
spec.require_paths = [ "lib" ]
|
|
30
28
|
|
|
31
|
-
spec.add_dependency "faraday", "~>
|
|
32
|
-
spec.add_dependency "faraday_middleware", "~> 1.1"
|
|
29
|
+
spec.add_dependency "faraday", "~> 2.11"
|
|
33
30
|
spec.add_dependency "faraday-multipart", "~> 1.0"
|
|
34
31
|
end
|
data/lib/free_agent/client.rb
CHANGED
|
@@ -25,7 +25,7 @@ module FreeAgent
|
|
|
25
25
|
def bank_accounts
|
|
26
26
|
BankAccountsResource.new(self)
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def bank_transactions
|
|
30
30
|
BankTransactionsResource.new(self)
|
|
31
31
|
end
|
|
@@ -74,14 +74,20 @@ module FreeAgent
|
|
|
74
74
|
BillsResource.new(self)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
def categories
|
|
78
|
+
CategoriesResource.new(self)
|
|
79
|
+
end
|
|
80
|
+
|
|
77
81
|
def connection
|
|
78
82
|
url = (sandbox == true ? SANDBOX_BASE_URL : BASE_URL)
|
|
79
83
|
@connection ||= Faraday.new(url) do |conn|
|
|
80
84
|
conn.request :authorization, :Bearer, access_token
|
|
81
85
|
conn.request :json
|
|
86
|
+
conn.response :json
|
|
82
87
|
|
|
83
|
-
conn.
|
|
84
|
-
|
|
88
|
+
conn.headers = {
|
|
89
|
+
"User-Agent" => "freeagentrb/v#{VERSION} (github.com/deanpcmad/freeagentrb)"
|
|
90
|
+
}
|
|
85
91
|
|
|
86
92
|
conn.adapter adapter, @stubs
|
|
87
93
|
end
|
|
@@ -95,6 +101,5 @@ module FreeAgent
|
|
|
95
101
|
conn.request :multipart
|
|
96
102
|
end
|
|
97
103
|
end
|
|
98
|
-
|
|
99
104
|
end
|
|
100
105
|
end
|
|
@@ -1,27 +1,46 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class Collection
|
|
3
|
-
attr_reader :data, :total
|
|
3
|
+
attr_reader :data, :total, :pagination
|
|
4
4
|
|
|
5
|
-
def self.from_response(response, type
|
|
5
|
+
def self.from_response(response, type:)
|
|
6
6
|
body = response.body
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
data = body[key].map { |attrs| type.new(attrs) }
|
|
10
|
-
else
|
|
11
|
-
data = body.map { |attrs| type.new(attrs) }
|
|
12
|
-
end
|
|
8
|
+
data = body.values.first.map { |attrs| type.new(attrs) }
|
|
13
9
|
|
|
14
10
|
total = response.headers["X-total-count"]
|
|
15
11
|
|
|
12
|
+
pagination = response.headers["Link"]&.split(", ")&.map do |link|
|
|
13
|
+
url, rel = link.match(/<(.+)>; rel='(.+)'/)&.captures
|
|
14
|
+
[ rel, url ]
|
|
15
|
+
end&.to_h
|
|
16
|
+
|
|
16
17
|
new(
|
|
17
18
|
data: data,
|
|
18
|
-
total: total
|
|
19
|
+
total: total,
|
|
20
|
+
pagination: pagination
|
|
19
21
|
)
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
def initialize(data:, total:)
|
|
24
|
+
def initialize(data:, total:, pagination: nil)
|
|
23
25
|
@data = data
|
|
24
26
|
@total = total
|
|
27
|
+
@pagination = pagination
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def count
|
|
31
|
+
data.count
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def each(&block)
|
|
35
|
+
data.each(&block)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def first
|
|
39
|
+
data.first
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def last
|
|
43
|
+
data.last
|
|
25
44
|
end
|
|
26
45
|
end
|
|
27
46
|
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module FreeAgent
|
|
2
|
+
class ErrorGenerator < StandardError
|
|
3
|
+
attr_reader :http_status_code
|
|
4
|
+
attr_reader :freeagent_error_code
|
|
5
|
+
attr_reader :freeagent_error_message
|
|
6
|
+
|
|
7
|
+
def initialize(response_body, http_status_code)
|
|
8
|
+
@response_body = response_body
|
|
9
|
+
@http_status_code = http_status_code
|
|
10
|
+
set_freeagent_error_values
|
|
11
|
+
super(build_message)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def set_freeagent_error_values
|
|
17
|
+
@freeagent_error_code = @response_body.dig("error")
|
|
18
|
+
@freeagent_error_message = @response_body.dig("message")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def error_message
|
|
22
|
+
@freeagent_error_message || @response_body.dig("error")
|
|
23
|
+
rescue NoMethodError
|
|
24
|
+
"An unknown error occurred."
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def build_message
|
|
28
|
+
if freeagent_error_code.nil?
|
|
29
|
+
return "Error #{@http_status_code}: #{error_message}"
|
|
30
|
+
end
|
|
31
|
+
"Error #{@http_status_code}: #{error_message} '#{freeagent_error_message}'"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
module Errors
|
|
36
|
+
class BadRequestError < ErrorGenerator
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def error_message
|
|
40
|
+
"Your request was malformed."
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class AuthenticationMissingError < ErrorGenerator
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def error_message
|
|
48
|
+
"You did not supply valid authentication credentials."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class ForbiddenError < ErrorGenerator
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def error_message
|
|
56
|
+
"You are not allowed to perform that action."
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class EntityNotFoundError < ErrorGenerator
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def error_message
|
|
64
|
+
"No results were found for your request."
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class ConflictError < ErrorGenerator
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def error_message
|
|
72
|
+
"Your request was a conflict."
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class UnprocessableContent < ErrorGenerator
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def error_message
|
|
80
|
+
"Your request was unprocessable."
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class TooManyRequestsError < ErrorGenerator
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def error_message
|
|
88
|
+
"Your request exceeded the API rate limit."
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class InternalError < ErrorGenerator
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
def error_message
|
|
96
|
+
"We were unable to perform the request due to server-side problems."
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class ServiceUnavailableError < ErrorGenerator
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def error_message
|
|
104
|
+
"You have been rate limited for sending more than 20 requests per second."
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class NotImplementedError < ErrorGenerator
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def error_message
|
|
112
|
+
"This resource has not been implemented."
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
class ErrorFactory
|
|
118
|
+
HTTP_ERROR_MAP = {
|
|
119
|
+
400 => Errors::BadRequestError,
|
|
120
|
+
401 => Errors::AuthenticationMissingError,
|
|
121
|
+
403 => Errors::ForbiddenError,
|
|
122
|
+
404 => Errors::EntityNotFoundError,
|
|
123
|
+
409 => Errors::ConflictError,
|
|
124
|
+
422 => Errors::UnprocessableContent,
|
|
125
|
+
429 => Errors::TooManyRequestsError,
|
|
126
|
+
500 => Errors::InternalError,
|
|
127
|
+
503 => Errors::ServiceUnavailableError,
|
|
128
|
+
501 => Errors::NotImplementedError
|
|
129
|
+
}.freeze
|
|
130
|
+
|
|
131
|
+
def self.create(response_body, http_status_code)
|
|
132
|
+
status = http_status_code
|
|
133
|
+
error_class = HTTP_ERROR_MAP[status] || ErrorGenerator
|
|
134
|
+
error_class.new(response_body, http_status_code) if error_class
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
data/lib/free_agent/object.rb
CHANGED
|
@@ -5,7 +5,7 @@ module FreeAgent
|
|
|
5
5
|
def initialize(attributes)
|
|
6
6
|
super to_ostruct(attributes)
|
|
7
7
|
|
|
8
|
-
# The FreeAgent API doesn't send an ID so generate it from the URL
|
|
8
|
+
# The FreeAgent API doesn't send an ID so generate it from the URL
|
|
9
9
|
if attributes["url"]
|
|
10
10
|
number = attributes["url"].match(/\d{2,}/)
|
|
11
11
|
self.id = number[0] unless number.nil?
|
|
@@ -14,7 +14,7 @@ module FreeAgent
|
|
|
14
14
|
|
|
15
15
|
def to_ostruct(obj)
|
|
16
16
|
if obj.is_a?(Hash)
|
|
17
|
-
OpenStruct.new(obj.map { |key, val| [key, to_ostruct(val)] }.to_h)
|
|
17
|
+
OpenStruct.new(obj.map { |key, val| [ key, to_ostruct(val) ] }.to_h)
|
|
18
18
|
elsif obj.is_a?(Array)
|
|
19
19
|
obj.map { |o| to_ostruct(o) }
|
|
20
20
|
else # Assumed to be a primitive value
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class BankTransaction < Object
|
|
3
|
+
def initialize(attributes)
|
|
4
|
+
super to_ostruct(attributes)
|
|
5
|
+
|
|
6
|
+
# Convert amounts to BigDecimal
|
|
7
|
+
self.amount = BigDecimal(self.amount.to_s).to_f if self.amount
|
|
8
|
+
self.unexplained_amount = BigDecimal(self.unexplained_amount.to_s).to_f if self.unexplained_amount
|
|
9
|
+
|
|
10
|
+
# Convert amounts in bank_transaction_explanations to BigDecimal
|
|
11
|
+
if self.bank_transaction_explanations
|
|
12
|
+
self.bank_transaction_explanations.each do |explanation|
|
|
13
|
+
explanation.id = explanation.url.match(/\d{2,}/)[0] if explanation.url
|
|
14
|
+
explanation.gross_value = BigDecimal(explanation.gross_value.to_s).to_f if explanation.gross_value
|
|
15
|
+
explanation.foreign_currency_value = BigDecimal(explanation.foreign_currency_value.to_s).to_f if explanation.foreign_currency_value
|
|
16
|
+
explanation.transfer_value = BigDecimal(explanation.transfer_value.to_s).to_f if explanation.transfer_value
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
3
20
|
end
|
|
4
21
|
end
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class Invoice < Object
|
|
3
|
+
def initialize(attributes)
|
|
4
|
+
super to_ostruct(attributes)
|
|
5
|
+
|
|
6
|
+
# Convert amounts to BigDecimal
|
|
7
|
+
self.net_value = BigDecimal(self.net_value.to_s).to_f if self.net_value
|
|
8
|
+
self.total_value = BigDecimal(self.total_value.to_s).to_f if self.total_value
|
|
9
|
+
self.paid_value = BigDecimal(self.paid_value.to_s).to_f if self.paid_value
|
|
10
|
+
self.due_value = BigDecimal(self.due_value.to_s).to_f if self.due_value
|
|
11
|
+
end
|
|
3
12
|
end
|
|
4
13
|
end
|
data/lib/free_agent/resource.rb
CHANGED
|
@@ -29,32 +29,20 @@ module FreeAgent
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def handle_response(response)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
else
|
|
47
|
-
raise Error, "Error 422: Unprocessable Entity. '#{response.body["errors"]["error"]["message"]}'"
|
|
48
|
-
end
|
|
49
|
-
when 429
|
|
50
|
-
raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["errors"]["error"]["message"]}'"
|
|
51
|
-
when 500
|
|
52
|
-
raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["errors"]["error"]["message"]}'"
|
|
53
|
-
when 503
|
|
54
|
-
raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["errors"]["error"]["message"]}'"
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
response
|
|
32
|
+
return true if response.status == 204
|
|
33
|
+
return response unless error?(response)
|
|
34
|
+
|
|
35
|
+
raise_error(response)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def error?(response)
|
|
39
|
+
[ 400, 401, 403, 404, 409, 422, 429, 500, 501, 503 ].include?(response.status) ||
|
|
40
|
+
response.body&.key?("error")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def raise_error(response)
|
|
44
|
+
error = FreeAgent::ErrorFactory.create(response.body, response.status)
|
|
45
|
+
raise error if error
|
|
58
46
|
end
|
|
59
47
|
end
|
|
60
48
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class AttachmentsResource < Resource
|
|
3
|
-
|
|
4
3
|
def retrieve(id:)
|
|
5
4
|
response = get_request("attachments/#{id}")
|
|
6
5
|
Attachment.new(response.body["attachment"])
|
|
@@ -10,6 +9,5 @@ module FreeAgent
|
|
|
10
9
|
response = delete_request("attachments/#{id}")
|
|
11
10
|
response.success?
|
|
12
11
|
end
|
|
13
|
-
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class BankAccountsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(view: nil)
|
|
5
4
|
url = view.nil? ? "bank_accounts" : "bank_accounts?view=#{view}"
|
|
6
5
|
|
|
7
6
|
response = get_request(url)
|
|
8
|
-
Collection.from_response(response, type: BankAccount
|
|
7
|
+
Collection.from_response(response, type: BankAccount)
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def retrieve(id:)
|
|
@@ -14,7 +13,7 @@ module FreeAgent
|
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
def create(type:, name:, opening_balance:, **params)
|
|
17
|
-
attributes = {type: type, name: name, opening_balance: opening_balance}
|
|
16
|
+
attributes = { type: type, name: name, opening_balance: opening_balance }
|
|
18
17
|
response = post_request("bank_accounts", body: attributes.merge(params))
|
|
19
18
|
BankAccount.new(response.body["bank_account"]) if response.success?
|
|
20
19
|
end
|
|
@@ -28,6 +27,5 @@ module FreeAgent
|
|
|
28
27
|
response = delete_request("bank_accounts/#{id}")
|
|
29
28
|
response.success?
|
|
30
29
|
end
|
|
31
|
-
|
|
32
30
|
end
|
|
33
31
|
end
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class BankTransactionExplanationsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(bank_account:, **params)
|
|
5
|
-
attributes = {bank_account: bank_account}
|
|
4
|
+
attributes = { bank_account: bank_account }
|
|
6
5
|
|
|
7
6
|
response = get_request("bank_transaction_explanations", params: attributes.merge(params))
|
|
8
|
-
Collection.from_response(response, type: BankTransactionExplanation
|
|
7
|
+
Collection.from_response(response, type: BankTransactionExplanation)
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def retrieve(id:)
|
|
@@ -13,17 +12,15 @@ module FreeAgent
|
|
|
13
12
|
BankTransactionExplanation.new(response.body["bank_transaction_explanation"])
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# end
|
|
15
|
+
def create(**params)
|
|
16
|
+
raise "bank_account or bank_transaction is required" unless !params[:bank_account].nil? || !params[:bank_transaction].nil?
|
|
17
|
+
response = post_request("bank_transaction_explanations", body: params)
|
|
18
|
+
BankTransactionExplanation.new(response.body["bank_transaction_explanation"])
|
|
19
|
+
end
|
|
22
20
|
|
|
23
21
|
def delete(id:)
|
|
24
22
|
response = delete_request("bank_transaction_explanations/#{id}")
|
|
25
23
|
response.success?
|
|
26
24
|
end
|
|
27
|
-
|
|
28
25
|
end
|
|
29
26
|
end
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class BankTransactionsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(bank_account:, **params)
|
|
5
|
-
attributes = {bank_account: bank_account}
|
|
4
|
+
attributes = { bank_account: bank_account }
|
|
6
5
|
|
|
7
6
|
response = get_request("bank_transactions", params: attributes.merge(params))
|
|
8
|
-
Collection.from_response(response, type: BankTransaction
|
|
7
|
+
Collection.from_response(response, type: BankTransaction)
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def retrieve(id:)
|
|
@@ -15,14 +14,14 @@ module FreeAgent
|
|
|
15
14
|
|
|
16
15
|
# Statement should be an array of transactions
|
|
17
16
|
def create(bank_account:, statement:)
|
|
18
|
-
response = post_request("bank_transactions/statement?bank_account=#{bank_account}", body: {statement: statement})
|
|
17
|
+
response = post_request("bank_transactions/statement?bank_account=#{bank_account}", body: { statement: statement })
|
|
19
18
|
response.success?
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def upload(bank_account:, statement:)
|
|
23
22
|
# This method uses Faraday Multipart (lostisland/faraday-multipart)
|
|
24
23
|
payload = {}
|
|
25
|
-
payload[:statement] = Faraday::Multipart::FilePart.new(statement,
|
|
24
|
+
payload[:statement] = Faraday::Multipart::FilePart.new(statement, "text/x-ruby")
|
|
26
25
|
|
|
27
26
|
response = client.connection_upload.post "bank_transactions/statement?bank_account=#{bank_account}", payload
|
|
28
27
|
response.success?
|
|
@@ -32,6 +31,5 @@ module FreeAgent
|
|
|
32
31
|
response = delete_request("bank_transactions/#{id}")
|
|
33
32
|
response.success?
|
|
34
33
|
end
|
|
35
|
-
|
|
36
34
|
end
|
|
37
35
|
end
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class BillsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("bills", params: params)
|
|
6
|
-
Collection.from_response(response, type: Bill
|
|
5
|
+
Collection.from_response(response, type: Bill)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_contact(contact:, **params)
|
|
10
9
|
response = get_request("bills?contact=#{contact}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Bill
|
|
10
|
+
Collection.from_response(response, type: Bill)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def list_for_project(project:, **params)
|
|
15
14
|
response = get_request("bills?project=#{project}", params: params)
|
|
16
|
-
Collection.from_response(response, type: Bill
|
|
15
|
+
Collection.from_response(response, type: Bill)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def retrieve(id:)
|
|
@@ -22,14 +21,14 @@ module FreeAgent
|
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def create(contact:, dated_on:, due_on:, reference:, bill_items:, **params)
|
|
25
|
-
attributes = {contact: contact, dated_on: dated_on, due_on: due_on, reference: reference, bill_items: bill_items}
|
|
24
|
+
attributes = { contact: contact, dated_on: dated_on, due_on: due_on, reference: reference, bill_items: bill_items }
|
|
26
25
|
|
|
27
|
-
response = post_request("bills", body: {bill: attributes.merge(params)})
|
|
26
|
+
response = post_request("bills", body: { bill: attributes.merge(params) })
|
|
28
27
|
Bill.new(response.body["bill"]) if response.success?
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def update(id:, **params)
|
|
32
|
-
response = put_request("bills/#{id}", body: {bill: params})
|
|
31
|
+
response = put_request("bills/#{id}", body: { bill: params })
|
|
33
32
|
Bill.new(response.body["bill"]) if response.success?
|
|
34
33
|
end
|
|
35
34
|
|
|
@@ -37,6 +36,5 @@ module FreeAgent
|
|
|
37
36
|
response = delete_request("bills/#{id}")
|
|
38
37
|
response.success?
|
|
39
38
|
end
|
|
40
|
-
|
|
41
39
|
end
|
|
42
40
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module FreeAgent
|
|
2
|
+
class CategoriesResource < Resource
|
|
3
|
+
def list(**params)
|
|
4
|
+
response = get_request("categories", params: params)
|
|
5
|
+
|
|
6
|
+
responses = []
|
|
7
|
+
|
|
8
|
+
response.body.keys.each do |key|
|
|
9
|
+
response.body[key].each do |value|
|
|
10
|
+
value["category_type"] = key
|
|
11
|
+
responses << Category.new(value)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
responses
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class ContactsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("contacts", params: params)
|
|
6
|
-
Collection.from_response(response, type: Contact
|
|
5
|
+
Collection.from_response(response, type: Contact)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def retrieve(id:)
|
|
@@ -27,6 +26,5 @@ module FreeAgent
|
|
|
27
26
|
response = delete_request("contacts/#{id}")
|
|
28
27
|
response.success?
|
|
29
28
|
end
|
|
30
|
-
|
|
31
29
|
end
|
|
32
30
|
end
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class CreditNotesResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("credit_notes", params: params)
|
|
6
|
-
Collection.from_response(response, type: CreditNote
|
|
5
|
+
Collection.from_response(response, type: CreditNote)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_contact(contact:, **params)
|
|
10
9
|
response = get_request("credit_notes?contact=#{contact}", params: params)
|
|
11
|
-
Collection.from_response(response, type: CreditNote
|
|
10
|
+
Collection.from_response(response, type: CreditNote)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def list_for_project(project:, **params)
|
|
15
14
|
response = get_request("credit_notes?project=#{project}", params: params)
|
|
16
|
-
Collection.from_response(response, type: CreditNote
|
|
15
|
+
Collection.from_response(response, type: CreditNote)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def retrieve(id:)
|
|
@@ -28,9 +27,9 @@ module FreeAgent
|
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def create(contact:, dated_on:, payment_terms_in_days: 0, **params)
|
|
31
|
-
attributes = {contact: contact, dated_on: dated_on, payment_terms_in_days: payment_terms_in_days}
|
|
30
|
+
attributes = { contact: contact, dated_on: dated_on, payment_terms_in_days: payment_terms_in_days }
|
|
32
31
|
|
|
33
|
-
response = post_request("credit_notes", body: {credit_note: attributes.merge(params)})
|
|
32
|
+
response = post_request("credit_notes", body: { credit_note: attributes.merge(params) })
|
|
34
33
|
CreditNote.new(response.body["credit_note"]) if response.success?
|
|
35
34
|
end
|
|
36
35
|
|
|
@@ -40,7 +39,7 @@ module FreeAgent
|
|
|
40
39
|
# end
|
|
41
40
|
|
|
42
41
|
def update(id:, **params)
|
|
43
|
-
response = put_request("credit_notes/#{id}", body: {credit_note: params})
|
|
42
|
+
response = put_request("credit_notes/#{id}", body: { credit_note: params })
|
|
44
43
|
CreditNote.new(response.body["credit_note"]) if response.success?
|
|
45
44
|
end
|
|
46
45
|
|
|
@@ -50,8 +49,8 @@ module FreeAgent
|
|
|
50
49
|
end
|
|
51
50
|
|
|
52
51
|
def email(id:, to:, **params)
|
|
53
|
-
attributes = {to: to}
|
|
54
|
-
response = post_request("credit_notes/#{id}/send_email", body: {credit_note: {email: attributes.merge(params)}})
|
|
52
|
+
attributes = { to: to }
|
|
53
|
+
response = post_request("credit_notes/#{id}/send_email", body: { credit_note: { email: attributes.merge(params) } })
|
|
55
54
|
response.success?
|
|
56
55
|
end
|
|
57
56
|
|
|
@@ -69,6 +68,5 @@ module FreeAgent
|
|
|
69
68
|
response = put_request("credit_notes/#{id}/transitions/mark_as_cancelled", body: {})
|
|
70
69
|
response.success?
|
|
71
70
|
end
|
|
72
|
-
|
|
73
71
|
end
|
|
74
72
|
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class EstimateItemsResource < Resource
|
|
3
|
-
|
|
4
3
|
def create(estimate:, **params)
|
|
5
|
-
attributes = {estimate: estimate}
|
|
4
|
+
attributes = { estimate: estimate }
|
|
6
5
|
|
|
7
6
|
response = post_request("estimate_items", body: attributes.merge(params))
|
|
8
7
|
EstimateItem.new(response.body["estimate_item"]) if response.success?
|
|
@@ -17,6 +16,5 @@ module FreeAgent
|
|
|
17
16
|
response = delete_request("estimate_items/#{id}")
|
|
18
17
|
response.success?
|
|
19
18
|
end
|
|
20
|
-
|
|
21
19
|
end
|
|
22
20
|
end
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class EstimatesResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("estimates", params: params)
|
|
6
|
-
Collection.from_response(response, type: Estimate
|
|
5
|
+
Collection.from_response(response, type: Estimate)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_contact(contact:, **params)
|
|
10
9
|
response = get_request("estimates?contact=#{contact}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Estimate
|
|
10
|
+
Collection.from_response(response, type: Estimate)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def list_for_project(project:, **params)
|
|
15
14
|
response = get_request("estimates?project=#{project}", params: params)
|
|
16
|
-
Collection.from_response(response, type: Estimate
|
|
15
|
+
Collection.from_response(response, type: Estimate)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def list_for_invoice(invoice:, **params)
|
|
20
19
|
response = get_request("estimates?invoice=#{invoice}", params: params)
|
|
21
|
-
Collection.from_response(response, type: Estimate
|
|
20
|
+
Collection.from_response(response, type: Estimate)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def retrieve(id:)
|
|
@@ -33,9 +32,9 @@ module FreeAgent
|
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
def create(contact:, dated_on:, currency:, reference:, status: "Draft", estimate_type: "Estimate", **params)
|
|
36
|
-
attributes = {contact: contact, dated_on: dated_on, status: status, estimate_type: estimate_type, currency: currency, reference: reference}
|
|
35
|
+
attributes = { contact: contact, dated_on: dated_on, status: status, estimate_type: estimate_type, currency: currency, reference: reference }
|
|
37
36
|
|
|
38
|
-
response = post_request("estimates", body: {estimate: attributes.merge(params)})
|
|
37
|
+
response = post_request("estimates", body: { estimate: attributes.merge(params) })
|
|
39
38
|
Estimate.new(response.body["estimate"]) if response.success?
|
|
40
39
|
end
|
|
41
40
|
|
|
@@ -50,8 +49,8 @@ module FreeAgent
|
|
|
50
49
|
end
|
|
51
50
|
|
|
52
51
|
def email(id:, to:, **params)
|
|
53
|
-
attributes = {to: to}
|
|
54
|
-
response = post_request("estimates/#{id}/send_email", body: {estimate: {email: attributes.merge(params)}})
|
|
52
|
+
attributes = { to: to }
|
|
53
|
+
response = post_request("estimates/#{id}/send_email", body: { estimate: { email: attributes.merge(params) } })
|
|
55
54
|
response.success?
|
|
56
55
|
end
|
|
57
56
|
|
|
@@ -74,6 +73,5 @@ module FreeAgent
|
|
|
74
73
|
response = put_request("estimates/#{id}/transitions/mark_as_rejected", body: {})
|
|
75
74
|
response.success?
|
|
76
75
|
end
|
|
77
|
-
|
|
78
76
|
end
|
|
79
77
|
end
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class InvoicesResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("invoices", params: params)
|
|
6
|
-
Collection.from_response(response, type: Invoice
|
|
5
|
+
Collection.from_response(response, type: Invoice)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_contact(contact:, **params)
|
|
10
9
|
response = get_request("invoices?contact=#{contact}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Invoice
|
|
10
|
+
Collection.from_response(response, type: Invoice)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def list_for_project(project:, **params)
|
|
15
14
|
response = get_request("invoices?project=#{project}", params: params)
|
|
16
|
-
Collection.from_response(response, type: Invoice
|
|
15
|
+
Collection.from_response(response, type: Invoice)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def retrieve(id:)
|
|
@@ -28,9 +27,9 @@ module FreeAgent
|
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def create(contact:, dated_on:, payment_terms_in_days: 0, **params)
|
|
31
|
-
attributes = {contact: contact, dated_on: dated_on, payment_terms_in_days: payment_terms_in_days}
|
|
30
|
+
attributes = { contact: contact, dated_on: dated_on, payment_terms_in_days: payment_terms_in_days }
|
|
32
31
|
|
|
33
|
-
response = post_request("invoices", body: {invoice: attributes.merge(params)})
|
|
32
|
+
response = post_request("invoices", body: { invoice: attributes.merge(params) })
|
|
34
33
|
Invoice.new(response.body["invoice"]) if response.success?
|
|
35
34
|
end
|
|
36
35
|
|
|
@@ -40,7 +39,7 @@ module FreeAgent
|
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
def update(id:, **params)
|
|
43
|
-
response = put_request("invoices/#{id}", body: {invoice: params})
|
|
42
|
+
response = put_request("invoices/#{id}", body: { invoice: params })
|
|
44
43
|
Invoice.new(response.body["invoice"]) if response.success?
|
|
45
44
|
end
|
|
46
45
|
|
|
@@ -50,8 +49,8 @@ module FreeAgent
|
|
|
50
49
|
end
|
|
51
50
|
|
|
52
51
|
def email(id:, to:, **params)
|
|
53
|
-
attributes = {to: to}
|
|
54
|
-
response = post_request("invoices/#{id}/send_email", body: {invoice: {email: attributes.merge(params)}})
|
|
52
|
+
attributes = { to: to }
|
|
53
|
+
response = post_request("invoices/#{id}/send_email", body: { invoice: { email: attributes.merge(params) } })
|
|
55
54
|
response.success?
|
|
56
55
|
end
|
|
57
56
|
|
|
@@ -84,6 +83,5 @@ module FreeAgent
|
|
|
84
83
|
response = post_request("invoices/#{id}/direct_debit", body: {})
|
|
85
84
|
response.success?
|
|
86
85
|
end
|
|
87
|
-
|
|
88
86
|
end
|
|
89
87
|
end
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class ProjectsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("projects", params: params)
|
|
6
|
-
Collection.from_response(response, type: Project
|
|
5
|
+
Collection.from_response(response, type: Project)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_contact(contact:, **params)
|
|
10
9
|
response = get_request("projects?contact=#{contact}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Project
|
|
10
|
+
Collection.from_response(response, type: Project)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def retrieve(id:)
|
|
@@ -17,7 +16,7 @@ module FreeAgent
|
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def create(contact:, name:, status:, currency:, budget_units:, **params)
|
|
20
|
-
attributes = {contact: contact, name: name, status: status, currency: currency, budget_units: budget_units}
|
|
19
|
+
attributes = { contact: contact, name: name, status: status, currency: currency, budget_units: budget_units }
|
|
21
20
|
|
|
22
21
|
response = post_request("projects", body: attributes.merge(params))
|
|
23
22
|
Project.new(response.body["project"]) if response.success?
|
|
@@ -32,6 +31,5 @@ module FreeAgent
|
|
|
32
31
|
response = delete_request("projects/#{id}")
|
|
33
32
|
response.success?
|
|
34
33
|
end
|
|
35
|
-
|
|
36
34
|
end
|
|
37
35
|
end
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class TasksResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("tasks", params: params)
|
|
6
|
-
Collection.from_response(response, type: Task
|
|
5
|
+
Collection.from_response(response, type: Task)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_project(project:, **params)
|
|
10
9
|
response = get_request("tasks?project=#{project}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Task
|
|
10
|
+
Collection.from_response(response, type: Task)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def retrieve(id:)
|
|
@@ -17,7 +16,7 @@ module FreeAgent
|
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def create(project:, name:, **params)
|
|
20
|
-
attributes = {project: project, name: name}
|
|
19
|
+
attributes = { project: project, name: name }
|
|
21
20
|
|
|
22
21
|
response = post_request("tasks", body: attributes.merge(params))
|
|
23
22
|
Task.new(response.body["task"]) if response.success?
|
|
@@ -32,6 +31,5 @@ module FreeAgent
|
|
|
32
31
|
response = delete_request("tasks/#{id}")
|
|
33
32
|
response.success?
|
|
34
33
|
end
|
|
35
|
-
|
|
36
34
|
end
|
|
37
35
|
end
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class TimeslipsResource < Resource
|
|
3
|
-
|
|
4
3
|
def list(**params)
|
|
5
4
|
response = get_request("timeslips", params: params)
|
|
6
|
-
Collection.from_response(response, type: Timeslip
|
|
5
|
+
Collection.from_response(response, type: Timeslip)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def list_for_user(user:, **params)
|
|
10
9
|
response = get_request("timeslips?user=#{user}", params: params)
|
|
11
|
-
Collection.from_response(response, type: Timeslip
|
|
10
|
+
Collection.from_response(response, type: Timeslip)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def list_for_task(task:, **params)
|
|
15
14
|
response = get_request("timeslips?task=#{task}", params: params)
|
|
16
|
-
Collection.from_response(response, type: Timeslip
|
|
15
|
+
Collection.from_response(response, type: Timeslip)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def list_for_project(project:, **params)
|
|
20
19
|
response = get_request("timeslips?project=#{project}", params: params)
|
|
21
|
-
Collection.from_response(response, type: Timeslip
|
|
20
|
+
Collection.from_response(response, type: Timeslip)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def retrieve(id:)
|
|
@@ -27,7 +26,7 @@ module FreeAgent
|
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
def create(task:, user:, project:, dated_on:, hours:, **params)
|
|
30
|
-
attributes = {task: task, user: user, project: project, dated_on: dated_on, hours: hours}
|
|
29
|
+
attributes = { task: task, user: user, project: project, dated_on: dated_on, hours: hours }
|
|
31
30
|
|
|
32
31
|
response = post_request("timeslips", body: attributes.merge(params))
|
|
33
32
|
Timeslip.new(response.body["timeslip"]) if response.success?
|
|
@@ -42,6 +41,5 @@ module FreeAgent
|
|
|
42
41
|
response = delete_request("timeslips/#{id}")
|
|
43
42
|
response.success?
|
|
44
43
|
end
|
|
45
|
-
|
|
46
44
|
end
|
|
47
45
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module FreeAgent
|
|
2
2
|
class UsersResource < Resource
|
|
3
|
-
|
|
4
3
|
def me
|
|
5
4
|
response = get_request("users/me")
|
|
6
5
|
User.new(response.body["user"])
|
|
@@ -8,7 +7,7 @@ module FreeAgent
|
|
|
8
7
|
|
|
9
8
|
def list(**params)
|
|
10
9
|
response = get_request("users", params: params)
|
|
11
|
-
Collection.from_response(response, type: User
|
|
10
|
+
Collection.from_response(response, type: User)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def retrieve(id:)
|
|
@@ -17,7 +16,7 @@ module FreeAgent
|
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def create(email:, first_name:, last_name:, role:, opening_mileage: 0, **params)
|
|
20
|
-
attributes = {email: email, first_name: first_name, last_name: last_name, role: role, opening_mileage: opening_mileage}
|
|
19
|
+
attributes = { email: email, first_name: first_name, last_name: last_name, role: role, opening_mileage: opening_mileage }
|
|
21
20
|
|
|
22
21
|
response = post_request("users", body: attributes.merge(params))
|
|
23
22
|
User.new(response.body["user"]) if response.success?
|
|
@@ -29,7 +28,7 @@ module FreeAgent
|
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def update_me(**params)
|
|
32
|
-
response = put_request("users/me", body: {user: params})
|
|
31
|
+
response = put_request("users/me", body: { user: params })
|
|
33
32
|
User.new(response.body["user"]) if response.success?
|
|
34
33
|
end
|
|
35
34
|
|
|
@@ -37,6 +36,5 @@ module FreeAgent
|
|
|
37
36
|
response = delete_request("users/#{id}")
|
|
38
37
|
response.success?
|
|
39
38
|
end
|
|
40
|
-
|
|
41
39
|
end
|
|
42
40
|
end
|
data/lib/free_agent/version.rb
CHANGED
data/lib/free_agent.rb
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
require "faraday"
|
|
2
|
-
require "faraday_middleware"
|
|
3
2
|
require "faraday/multipart"
|
|
4
3
|
require "json"
|
|
5
4
|
|
|
6
5
|
require_relative "free_agent/version"
|
|
7
6
|
|
|
8
7
|
module FreeAgent
|
|
8
|
+
autoload :Error, "free_agent/error"
|
|
9
|
+
autoload :Errors, "free_agent/error_generator"
|
|
10
|
+
autoload :ErrorGenerator, "free_agent/error_generator"
|
|
11
|
+
autoload :ErrorFactory, "free_agent/error_generator"
|
|
9
12
|
|
|
10
13
|
autoload :Client, "free_agent/client"
|
|
11
14
|
autoload :Collection, "free_agent/collection"
|
|
@@ -28,6 +31,7 @@ module FreeAgent
|
|
|
28
31
|
autoload :EstimateItemsResource, "free_agent/resources/estimate_items"
|
|
29
32
|
autoload :CreditNotesResource, "free_agent/resources/credit_notes"
|
|
30
33
|
autoload :BillsResource, "free_agent/resources/bills"
|
|
34
|
+
autoload :CategoriesResource, "free_agent/resources/categories"
|
|
31
35
|
|
|
32
36
|
autoload :Company, "free_agent/objects/company"
|
|
33
37
|
autoload :Contact, "free_agent/objects/contact"
|
|
@@ -44,5 +48,5 @@ module FreeAgent
|
|
|
44
48
|
autoload :EstimateItem, "free_agent/objects/estimate_item"
|
|
45
49
|
autoload :CreditNote, "free_agent/objects/credit_note"
|
|
46
50
|
autoload :Bill, "free_agent/objects/bill"
|
|
47
|
-
|
|
51
|
+
autoload :Category, "free_agent/objects/category"
|
|
48
52
|
end
|
data/lib/freeagentrb.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require "free_agent"
|
|
1
|
+
require "free_agent"
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: freeagentrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dean Perry
|
|
8
|
-
|
|
9
|
-
bindir: exe
|
|
8
|
+
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-02-13 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: faraday
|
|
@@ -16,28 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '2.11'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: faraday_middleware
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.1'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1.1'
|
|
25
|
+
version: '2.11'
|
|
41
26
|
- !ruby/object:Gem::Dependency
|
|
42
27
|
name: faraday-multipart
|
|
43
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,7 +37,6 @@ dependencies:
|
|
|
52
37
|
- - "~>"
|
|
53
38
|
- !ruby/object:Gem::Version
|
|
54
39
|
version: '1.0'
|
|
55
|
-
description:
|
|
56
40
|
email:
|
|
57
41
|
- dean@deanpcmad.com
|
|
58
42
|
executables: []
|
|
@@ -60,6 +44,7 @@ extensions: []
|
|
|
60
44
|
extra_rdoc_files: []
|
|
61
45
|
files:
|
|
62
46
|
- ".env.example"
|
|
47
|
+
- ".rubocop.yml"
|
|
63
48
|
- Gemfile
|
|
64
49
|
- Gemfile.lock
|
|
65
50
|
- LICENSE.txt
|
|
@@ -72,12 +57,14 @@ files:
|
|
|
72
57
|
- lib/free_agent/client.rb
|
|
73
58
|
- lib/free_agent/collection.rb
|
|
74
59
|
- lib/free_agent/error.rb
|
|
60
|
+
- lib/free_agent/error_generator.rb
|
|
75
61
|
- lib/free_agent/object.rb
|
|
76
62
|
- lib/free_agent/objects/attachment.rb
|
|
77
63
|
- lib/free_agent/objects/bank_account.rb
|
|
78
64
|
- lib/free_agent/objects/bank_transaction.rb
|
|
79
65
|
- lib/free_agent/objects/bank_transaction_explanation.rb
|
|
80
66
|
- lib/free_agent/objects/bill.rb
|
|
67
|
+
- lib/free_agent/objects/category.rb
|
|
81
68
|
- lib/free_agent/objects/company.rb
|
|
82
69
|
- lib/free_agent/objects/contact.rb
|
|
83
70
|
- lib/free_agent/objects/credit_note.rb
|
|
@@ -94,6 +81,7 @@ files:
|
|
|
94
81
|
- lib/free_agent/resources/bank_transaction_explanations.rb
|
|
95
82
|
- lib/free_agent/resources/bank_transactions.rb
|
|
96
83
|
- lib/free_agent/resources/bills.rb
|
|
84
|
+
- lib/free_agent/resources/categories.rb
|
|
97
85
|
- lib/free_agent/resources/company.rb
|
|
98
86
|
- lib/free_agent/resources/contacts.rb
|
|
99
87
|
- lib/free_agent/resources/credit_notes.rb
|
|
@@ -111,7 +99,7 @@ licenses:
|
|
|
111
99
|
- MIT
|
|
112
100
|
metadata:
|
|
113
101
|
homepage_uri: https://deanpcmad.com
|
|
114
|
-
|
|
102
|
+
source_code_uri: https://github.com/deanpcmad/freeagentrb
|
|
115
103
|
rdoc_options: []
|
|
116
104
|
require_paths:
|
|
117
105
|
- lib
|
|
@@ -126,8 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
114
|
- !ruby/object:Gem::Version
|
|
127
115
|
version: '0'
|
|
128
116
|
requirements: []
|
|
129
|
-
rubygems_version: 3.
|
|
130
|
-
signing_key:
|
|
117
|
+
rubygems_version: 3.6.2
|
|
131
118
|
specification_version: 4
|
|
132
|
-
summary:
|
|
119
|
+
summary: Ruby library for the FreeAgent v2 API
|
|
133
120
|
test_files: []
|