elmas 2.4.2 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/Gemfile +3 -1
- data/Guardfile +6 -4
- data/README.md +15 -4
- data/Rakefile +3 -1
- data/elmas.gemspec +17 -15
- data/lib/elmas.rb +11 -2
- data/lib/elmas/api.rb +2 -0
- data/lib/elmas/client.rb +2 -0
- data/lib/elmas/config.rb +28 -21
- data/lib/elmas/exception.rb +2 -0
- data/lib/elmas/oauth.rb +40 -4
- data/lib/elmas/parser.rb +2 -0
- data/lib/elmas/request.rb +2 -0
- data/lib/elmas/resource.rb +7 -5
- data/lib/elmas/resources/account.rb +27 -24
- data/lib/elmas/resources/aging_receivables_list.rb +8 -6
- data/lib/elmas/resources/bank_account.rb +13 -19
- data/lib/elmas/resources/bank_entry.rb +6 -4
- data/lib/elmas/resources/bank_entry_line.rb +6 -4
- data/lib/elmas/resources/base_entry_line.rb +10 -6
- data/lib/elmas/resources/cash_entry.rb +22 -0
- data/lib/elmas/resources/cash_entry_line.rb +20 -0
- data/lib/elmas/resources/contact.rb +10 -8
- data/lib/elmas/resources/costcenter.rb +4 -2
- data/lib/elmas/resources/costunit.rb +4 -2
- data/lib/elmas/resources/division.rb +26 -0
- data/lib/elmas/resources/document.rb +7 -5
- data/lib/elmas/resources/document_attachment.rb +3 -1
- data/lib/elmas/resources/general_journal_entry.rb +4 -2
- data/lib/elmas/resources/general_journal_entry_line.rb +2 -0
- data/lib/elmas/resources/gl_account.rb +11 -9
- data/lib/elmas/resources/item.rb +21 -18
- data/lib/elmas/resources/item_group.rb +4 -2
- data/lib/elmas/resources/journal.rb +6 -4
- data/lib/elmas/resources/layout.rb +6 -4
- data/lib/elmas/resources/mailbox.rb +6 -4
- data/lib/elmas/resources/payment_condition.rb +9 -7
- data/lib/elmas/resources/printed_sales_invoice.rb +12 -10
- data/lib/elmas/resources/project.rb +11 -19
- data/lib/elmas/resources/purchase_entry.rb +5 -6
- data/lib/elmas/resources/purchase_entry_line.rb +2 -0
- data/lib/elmas/resources/receivables_list.rb +4 -5
- data/lib/elmas/resources/sales_entry.rb +5 -7
- data/lib/elmas/resources/sales_entry_line.rb +2 -0
- data/lib/elmas/resources/sales_invoice.rb +4 -5
- data/lib/elmas/resources/sales_invoice_line.rb +4 -5
- data/lib/elmas/resources/sales_item_prices.rb +4 -5
- data/lib/elmas/resources/sales_order.rb +4 -5
- data/lib/elmas/resources/sales_order_line.rb +4 -5
- data/lib/elmas/resources/shared_sales_attributes.rb +6 -11
- data/lib/elmas/resources/time_transaction.rb +8 -12
- data/lib/elmas/resources/transaction.rb +4 -2
- data/lib/elmas/resources/transaction_line.rb +4 -2
- data/lib/elmas/resources/vat_code.rb +5 -8
- data/lib/elmas/response.rb +5 -2
- data/lib/elmas/result_set.rb +4 -2
- data/lib/elmas/sanitizer.rb +7 -5
- data/lib/elmas/uri.rb +2 -0
- data/lib/elmas/utils.rb +2 -0
- data/lib/elmas/version.rb +4 -2
- metadata +29 -27
- data/lib/elmas/log.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3beb2738aa3a94532e1e4f032a229f87e94aa08
|
4
|
+
data.tar.gz: 37ecf10dae1c0baf831cd221f15c900959d7137b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb404ddad916430568cc25e593d52b06b0e8e35c4b211c78a8587e866c12e8de69b9ff5bee4f2a73659e49c274159cc034c12083592ab7cf146567be1ba3af1c
|
7
|
+
data.tar.gz: 299d31e087f5f2c7847e99cf81cde26e47db46c589216bed196177e75e6e884b69b53a4ea36435897b59d4a69fd3ef0935e523c8d0906cc72580670c1a531f36
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :rspec, cmd: "rspec" do
|
2
4
|
watch(%r{^spec/.+_spec\.rb$})
|
3
5
|
watch(%r{^lib/(.+)\.rb$}) { "spec" }
|
4
|
-
watch(
|
6
|
+
watch("spec/spec_helper.rb") { "spec" }
|
5
7
|
end
|
6
8
|
|
7
|
-
guard :rubocop, all_on_start: false, cli: [
|
9
|
+
guard :rubocop, all_on_start: false, cli: ["--format", "clang", "--rails"] do
|
8
10
|
watch(%r{^spec/.+_spec\.rb$})
|
9
11
|
watch(%r{^lib/(.+)\.rb$})
|
10
|
-
watch(
|
12
|
+
watch("spec/spec_helper.rb")
|
11
13
|
end
|
data/README.md
CHANGED
@@ -18,6 +18,8 @@ Elmas means diamond, but in this case it's an API wrapper for [Exact Online](htt
|
|
18
18
|
* [mipmip](https://github.com/mipmip)
|
19
19
|
* [Bramjetten](https://github.com/Bramjetten)
|
20
20
|
* [LaurensN](https://github.com/LaurensN)
|
21
|
+
* [jdlombardozzi](https://github.com/jdlombardozzi)
|
22
|
+
* [michielverkoijen](https://github.com/michielverkoijen)
|
21
23
|
|
22
24
|
Thanks for helping! If you want to contribute read through this readme how to!
|
23
25
|
|
@@ -75,11 +77,8 @@ So combining all of this results in
|
|
75
77
|
Elmas.configure do |config|
|
76
78
|
config.client_id = ENV['CLIENT_ID']
|
77
79
|
config.client_secret = ENV['CLIENT_SECRET']
|
78
|
-
|
79
|
-
Elmas.configure do |config|
|
80
|
+
config.redirect_uri = ENV['REDIRECT_URI']
|
80
81
|
config.access_token = Elmas.authorize(ENV['EXACT_USER_NAME'], ENV['EXACT_PASSWORD']).access_token
|
81
|
-
end
|
82
|
-
Elmas.configure do |config|
|
83
82
|
config.division = Elmas.authorize_division
|
84
83
|
end
|
85
84
|
```
|
@@ -98,6 +97,18 @@ unless Elmas.authorized?
|
|
98
97
|
end
|
99
98
|
```
|
100
99
|
|
100
|
+
### Logger
|
101
|
+
|
102
|
+
The default logger is STDOUT. A custom logger can be be configured.
|
103
|
+
```ruby
|
104
|
+
dir = File.dirname("./tmp/errors.log")
|
105
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
106
|
+
|
107
|
+
Elmas.configure do |config|
|
108
|
+
config.logger = ::Logger.new("./tmp/errors.log", "daily")
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
101
112
|
## Accessing the API
|
102
113
|
|
103
114
|
We can retrieve data from the API using the following syntax.
|
data/Rakefile
CHANGED
data/elmas.gemspec
CHANGED
@@ -1,37 +1,39 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
5
|
+
require "elmas/version"
|
5
6
|
|
7
|
+
# rubocop:disable Metrics/BlockLength
|
6
8
|
Gem::Specification.new do |spec|
|
7
9
|
spec.name = "elmas"
|
8
10
|
spec.authors = ["Marthyn"]
|
9
11
|
spec.email = ["MarthynOlthof@hoppinger.nl"]
|
10
12
|
|
11
|
-
spec.summary =
|
13
|
+
spec.summary = "API wrapper for Exact Online"
|
12
14
|
spec.homepage = "https://github.com/exactonline/exactonline-api-ruby-client"
|
13
|
-
spec.licenses = %w
|
15
|
+
spec.licenses = %w[MIT]
|
14
16
|
|
15
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
|
16
|
-
spec.require_paths = %w
|
18
|
+
spec.require_paths = %w[lib]
|
17
19
|
spec.version = Elmas::Version.to_s
|
18
20
|
|
21
|
+
spec.add_dependency "activeresource"
|
22
|
+
spec.add_dependency "activesupport"
|
19
23
|
spec.add_dependency "faraday", [">= 0.12.1"]
|
20
24
|
spec.add_dependency "mechanize", ">= 2.7.5"
|
21
|
-
spec.add_dependency "activesupport"
|
22
|
-
spec.add_dependency "activeresource"
|
23
25
|
|
24
26
|
spec.add_development_dependency "bundler"
|
27
|
+
spec.add_development_dependency "dotenv"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
spec.add_development_dependency "guard-rubocop"
|
30
|
+
spec.add_development_dependency "listen"
|
31
|
+
spec.add_development_dependency "mutant-rspec"
|
25
32
|
spec.add_development_dependency "rake"
|
26
33
|
spec.add_development_dependency "rspec"
|
34
|
+
spec.add_development_dependency "ruby_dep"
|
35
|
+
spec.add_development_dependency "rubycritic"
|
27
36
|
spec.add_development_dependency "simplecov"
|
28
37
|
spec.add_development_dependency "simplecov-rcov"
|
29
38
|
spec.add_development_dependency "webmock"
|
30
|
-
spec.add_development_dependency "rubycritic"
|
31
|
-
spec.add_development_dependency "guard-rspec"
|
32
|
-
spec.add_development_dependency "guard-rubocop"
|
33
|
-
spec.add_development_dependency "listen"
|
34
|
-
spec.add_development_dependency "ruby_dep"
|
35
|
-
spec.add_development_dependency "mutant-rspec"
|
36
|
-
spec.add_development_dependency "dotenv"
|
37
39
|
end
|
data/lib/elmas.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "elmas/version"
|
2
4
|
require "elmas/api"
|
3
5
|
require "elmas/config"
|
4
6
|
require "elmas/response"
|
5
7
|
require "elmas/client"
|
6
|
-
require "elmas/log"
|
7
8
|
require "elmas/resource"
|
8
9
|
require "elmas/result_set"
|
9
10
|
require "elmas/sanitizer"
|
@@ -44,10 +45,10 @@ require "elmas/resources/vat_code"
|
|
44
45
|
require "elmas/resources/general_journal_entry"
|
45
46
|
require "elmas/resources/general_journal_entry_line"
|
46
47
|
require "elmas/resources/payment_condition"
|
48
|
+
require "elmas/resources/division"
|
47
49
|
|
48
50
|
module Elmas
|
49
51
|
extend Config
|
50
|
-
extend Log
|
51
52
|
|
52
53
|
def self.client(options = {})
|
53
54
|
Elmas::Client.new(options)
|
@@ -63,4 +64,12 @@ module Elmas
|
|
63
64
|
def self.respond_to?(method, include_all = false)
|
64
65
|
client.respond_to?(method, include_all) || super
|
65
66
|
end
|
67
|
+
|
68
|
+
def self.info(msg)
|
69
|
+
logger.info(msg)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.error(msg)
|
73
|
+
logger.error(msg)
|
74
|
+
end
|
66
75
|
end
|
data/lib/elmas/api.rb
CHANGED
data/lib/elmas/client.rb
CHANGED
data/lib/elmas/config.rb
CHANGED
@@ -1,29 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "faraday"
|
2
4
|
require "active_resource/threadsafe_attributes"
|
5
|
+
require "logger"
|
3
6
|
|
4
7
|
module Elmas
|
5
8
|
module Config
|
6
9
|
include ThreadsafeAttributes
|
7
10
|
# An array of valid keys in the options hash
|
8
|
-
VALID_OPTIONS_KEYS = [
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
11
|
+
VALID_OPTIONS_KEYS = %i[
|
12
|
+
access_token
|
13
|
+
adapter
|
14
|
+
client_id
|
15
|
+
client_secret
|
16
|
+
connection_options
|
17
|
+
redirect_uri
|
18
|
+
response_format
|
19
|
+
user_agent
|
20
|
+
endpoint
|
21
|
+
division
|
22
|
+
base_url
|
23
|
+
refresh_token
|
24
|
+
logger
|
21
25
|
].freeze
|
22
26
|
|
23
27
|
# By default, don't set a user access token
|
24
|
-
DEFAULT_ACCESS_TOKEN = ""
|
28
|
+
DEFAULT_ACCESS_TOKEN = ""
|
25
29
|
|
26
|
-
DEFAULT_REFRESH_TOKEN = ""
|
30
|
+
DEFAULT_REFRESH_TOKEN = ""
|
27
31
|
|
28
32
|
# The adapter that will be used to connect if none is set
|
29
33
|
#
|
@@ -31,27 +35,27 @@ module Elmas
|
|
31
35
|
DEFAULT_ADAPTER = Faraday.default_adapter
|
32
36
|
|
33
37
|
# By default, client id should be set in .env
|
34
|
-
DEFAULT_CLIENT_ID = ""
|
38
|
+
DEFAULT_CLIENT_ID = ""
|
35
39
|
|
36
40
|
# By default, client secret should be set in .env
|
37
|
-
DEFAULT_CLIENT_SECRET = ""
|
41
|
+
DEFAULT_CLIENT_SECRET = ""
|
38
42
|
|
39
43
|
# By default, don't set any connection options
|
40
44
|
DEFAULT_CONNECTION_OPTIONS = {}.freeze
|
41
45
|
|
42
|
-
DEFAULT_BASE_URL = "https://start.exactonline.nl"
|
46
|
+
DEFAULT_BASE_URL = "https://start.exactonline.nl"
|
43
47
|
|
44
48
|
# The endpoint that will be used to connect if none is set
|
45
|
-
DEFAULT_ENDPOINT = "api/v1"
|
49
|
+
DEFAULT_ENDPOINT = "api/v1"
|
46
50
|
|
47
51
|
# the division code you want to connect with
|
48
|
-
DEFAULT_DIVISION = ""
|
52
|
+
DEFAULT_DIVISION = ""
|
49
53
|
|
50
54
|
# The response format appended to the path and sent in the 'Accept' header if none is set
|
51
55
|
#
|
52
56
|
DEFAULT_FORMAT = :json
|
53
57
|
|
54
|
-
DEFAULT_REDIRECT_URI = "https://www.getpostman.com/oauth2/callback"
|
58
|
+
DEFAULT_REDIRECT_URI = "https://www.getpostman.com/oauth2/callback"
|
55
59
|
|
56
60
|
# By default, don't set user agent
|
57
61
|
DEFAULT_USER_AGENT = nil
|
@@ -59,6 +63,8 @@ module Elmas
|
|
59
63
|
# An array of valid request/response formats
|
60
64
|
VALID_FORMATS = [:json].freeze
|
61
65
|
|
66
|
+
DEFAULT_LOGGER = ::Logger.new(STDOUT)
|
67
|
+
|
62
68
|
# @private
|
63
69
|
threadsafe_attribute(*VALID_OPTIONS_KEYS)
|
64
70
|
|
@@ -93,6 +99,7 @@ module Elmas
|
|
93
99
|
self.response_format = DEFAULT_FORMAT
|
94
100
|
self.user_agent = DEFAULT_USER_AGENT
|
95
101
|
self.refresh_token = DEFAULT_REFRESH_TOKEN
|
102
|
+
self.logger = DEFAULT_LOGGER
|
96
103
|
end
|
97
104
|
end
|
98
105
|
end
|
data/lib/elmas/exception.rb
CHANGED
data/lib/elmas/oauth.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "mechanize"
|
2
4
|
require "uri"
|
3
5
|
require "json"
|
@@ -7,6 +9,7 @@ require File.expand_path("../response", __FILE__)
|
|
7
9
|
|
8
10
|
# from https://developers.exactonline.com/#Example retrieve access token.html
|
9
11
|
module Elmas
|
12
|
+
# rubocop:disable Metrics/ModuleLength
|
10
13
|
module OAuth
|
11
14
|
def authorize(user_name, password, options = {})
|
12
15
|
agent = Mechanize.new
|
@@ -18,6 +21,15 @@ module Elmas
|
|
18
21
|
OauthResponse.new(get_access_token(code))
|
19
22
|
end
|
20
23
|
|
24
|
+
def refresh_authorization
|
25
|
+
OauthResponse.new(get_refresh_token(refresh_token)).tap do |response|
|
26
|
+
Elmas.configure do |config|
|
27
|
+
config.access_token = response.access_token
|
28
|
+
config.refresh_token = response.refresh_token
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
def authorized?
|
22
34
|
# Do a test call, return false if 401 or any error code
|
23
35
|
get("/Current/Me", no_division: true)
|
@@ -32,13 +44,10 @@ module Elmas
|
|
32
44
|
|
33
45
|
def auto_authorize
|
34
46
|
Elmas.configure do |config|
|
47
|
+
config.redirect_uri = ENV["REDIRECT_URI"]
|
35
48
|
config.client_id = ENV["CLIENT_ID"]
|
36
49
|
config.client_secret = ENV["CLIENT_SECRET"]
|
37
|
-
end
|
38
|
-
Elmas.configure do |config|
|
39
50
|
config.access_token = Elmas.authorize(ENV["EXACT_USER_NAME"], ENV["EXACT_PASSWORD"]).access_token
|
40
|
-
end
|
41
|
-
Elmas.configure do |config|
|
42
51
|
config.division = Elmas.authorize_division
|
43
52
|
end
|
44
53
|
end
|
@@ -67,6 +76,23 @@ module Elmas
|
|
67
76
|
end
|
68
77
|
end
|
69
78
|
|
79
|
+
# Return an access token from authorization via refresh token
|
80
|
+
def get_refresh_token(refresh_token)
|
81
|
+
conn = Faraday.new(url: config[:base_url]) do |faraday|
|
82
|
+
faraday.request :url_encoded
|
83
|
+
faraday.adapter Faraday.default_adapter
|
84
|
+
end
|
85
|
+
|
86
|
+
params = refresh_access_token_params(refresh_token)
|
87
|
+
|
88
|
+
conn.post do |req|
|
89
|
+
req.url "/api/oauth2/token"
|
90
|
+
req.body = params
|
91
|
+
req.headers["Accept"] = "application/json"
|
92
|
+
req.headers["Content-Type"] = "application/x-www-form-urlencoded"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
70
96
|
private
|
71
97
|
|
72
98
|
def login(agent, user_name, password, options)
|
@@ -81,6 +107,7 @@ module Elmas
|
|
81
107
|
|
82
108
|
def allow_access(agent)
|
83
109
|
return if agent.page.uri.to_s.include?("getpostman")
|
110
|
+
return if agent.page.uri.to_s.include?(redirect_uri)
|
84
111
|
form = agent.page.form_with(id: "PublicOAuth2Form")
|
85
112
|
button = form.button_with(id: "AllowButton")
|
86
113
|
agent.submit(form, button)
|
@@ -101,6 +128,15 @@ module Elmas
|
|
101
128
|
redirect_uri: redirect_uri
|
102
129
|
}
|
103
130
|
end
|
131
|
+
|
132
|
+
def refresh_access_token_params(code)
|
133
|
+
{
|
134
|
+
client_id: client_id,
|
135
|
+
client_secret: client_secret,
|
136
|
+
grant_type: "refresh_token",
|
137
|
+
refresh_token: code
|
138
|
+
}
|
139
|
+
end
|
104
140
|
end
|
105
141
|
end
|
106
142
|
|
data/lib/elmas/parser.rb
CHANGED
data/lib/elmas/request.rb
CHANGED
data/lib/elmas/resource.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path("../utils", __FILE__)
|
2
4
|
require File.expand_path("../exception", __FILE__)
|
3
5
|
require File.expand_path("../uri", __FILE__)
|
@@ -24,8 +26,8 @@ module Elmas
|
|
24
26
|
def find_all(options = {})
|
25
27
|
@order_by = options[:order_by]
|
26
28
|
@select = options[:select]
|
27
|
-
response = get(uri([
|
28
|
-
response
|
29
|
+
response = get(uri(%i[order select]))
|
30
|
+
response&.results
|
29
31
|
end
|
30
32
|
|
31
33
|
# Pass filters in an array, for example 'filters: [:id, :name]'
|
@@ -33,14 +35,14 @@ module Elmas
|
|
33
35
|
@filters = options[:filters]
|
34
36
|
@order_by = options[:order_by]
|
35
37
|
@select = options[:select]
|
36
|
-
response = get(uri([
|
37
|
-
response
|
38
|
+
response = get(uri(%i[order select filters]))
|
39
|
+
response&.results
|
38
40
|
end
|
39
41
|
|
40
42
|
def find
|
41
43
|
return nil unless id?
|
42
44
|
response = get(uri([:id]))
|
43
|
-
response
|
45
|
+
response&.results&.first
|
44
46
|
end
|
45
47
|
|
46
48
|
# Normally use the url method (which applies the filters) but sometimes you only want to use the base path or other paths
|