jortt 3.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec.yml +40 -0
  3. data/.ruby-version +1 -1
  4. data/README.md +81 -46
  5. data/Rakefile +0 -1
  6. data/jortt.gemspec +10 -10
  7. data/lib/jortt.rb +0 -1
  8. data/lib/jortt/client.rb +75 -23
  9. data/lib/jortt/client/customers.rb +91 -0
  10. data/lib/jortt/client/error.rb +33 -0
  11. data/lib/jortt/client/invoices.rb +80 -0
  12. data/lib/jortt/client/ledger_accounts.rb +27 -0
  13. data/lib/jortt/client/version.rb +1 -2
  14. data/spec/fixtures/vcr_cassettes/Jortt/_client/1_1_1.yml +64 -0
  15. data/spec/fixtures/vcr_cassettes/Jortt_Client/configured/_customers/1_1_1_1.yml +64 -0
  16. data/spec/fixtures/vcr_cassettes/Jortt_Client/configured/_invoices/1_1_2_1.yml +64 -0
  17. data/spec/fixtures/vcr_cassettes/Jortt_Client/configured/_ledger_accounts/1_1_3_1.yml +64 -0
  18. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_create/faulty_payload/shows_a_nice_error.yml +413 -0
  19. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_create/valid_payload/creates_the_customer.yml +505 -0
  20. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_delete/deletes_the_customer.yml +505 -0
  21. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_direct_debit_mandate/sends_direct_debit_mandate_to_the_customer_or_responds_with_an_error_when_not_possible.yml +470 -0
  22. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_index/query/returns_the_queried_customers.yml +464 -0
  23. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_index/without_params/returns_customers.yml +415 -0
  24. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_show/returns_the_customer.yml +464 -0
  25. data/spec/fixtures/vcr_cassettes/Jortt_Client_Customers/_update/updates_the_customer.yml +603 -0
  26. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_create/creates_the_invoice.yml +170 -0
  27. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_credit/credits_the_invoice.yml +374 -0
  28. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_download/returns_the_invoice_download_link.yml +168 -0
  29. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_index/invoice_status/returns_those_invoices.yml +776 -0
  30. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_index/query/returns_the_queried_invoices.yml +315 -0
  31. data/spec/fixtures/vcr_cassettes/Jortt_Client_Invoices/_show/returns_the_invoice.yml +421 -0
  32. data/spec/fixtures/vcr_cassettes/Jortt_Client_LedgerAccounts/_index/returns_invoices.yml +118 -0
  33. data/spec/jortt/client/customers_spec.rb +104 -0
  34. data/spec/jortt/client/invoices_spec.rb +129 -0
  35. data/spec/jortt/client/ledger_accounts_spec.rb +19 -0
  36. data/spec/jortt/client_spec.rb +9 -30
  37. data/spec/{freemle_spec.rb → jortt_spec.rb} +2 -3
  38. data/spec/spec_helper.rb +18 -4
  39. metadata +95 -46
  40. data/.rubocop.yml +0 -26
  41. data/.travis.yml +0 -7
  42. data/lib/jortt/client/resource.rb +0 -140
  43. data/spec/jortt/client/resource_spec.rb +0 -31
@@ -0,0 +1,118 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://app.jortt.nl/oauth-provider/oauth/token
6
+ body:
7
+ encoding: UTF-8
8
+ string: grant_type=client_credentials&scope=invoices%3Aread+invoices%3Awrite+customers%3Aread+customers%3Awrite
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Date:
24
+ - Thu, 24 Sep 2020 15:03:35 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Status:
32
+ - 200 OK
33
+ Cache-Control:
34
+ - private, no-store
35
+ Referrer-Policy:
36
+ - strict-origin-when-cross-origin
37
+ X-Permitted-Cross-Domain-Policies:
38
+ - none
39
+ Pragma:
40
+ - no-cache
41
+ X-Xss-Protection:
42
+ - 1; mode=block
43
+ X-Request-Id:
44
+ - d83ae9ab-c629-46a3-8536-3d48345bbc24
45
+ X-Download-Options:
46
+ - noopen
47
+ Etag:
48
+ - W/"0fb39157c79bce6700240fe1ea97876e"
49
+ X-Frame-Options:
50
+ - SAMEORIGIN
51
+ X-Runtime:
52
+ - '0.333943'
53
+ X-Content-Type-Options:
54
+ - nosniff
55
+ X-Powered-By:
56
+ - Phusion Passenger
57
+ Server:
58
+ - nginx + Phusion Passenger
59
+ body:
60
+ encoding: UTF-8
61
+ string: '{"access_token":"-OQjJQikSmMhA9USfhfgESp3DKCWUUOGBfclpyF0oic","token_type":"Bearer","expires_in":7200,"scope":"invoices:read
62
+ invoices:write customers:read customers:write","created_at":1600959815}'
63
+ recorded_at: Thu, 24 Sep 2020 15:03:35 GMT
64
+ - request:
65
+ method: get
66
+ uri: https://api.jortt.nl/ledger_accounts/invoices
67
+ body:
68
+ encoding: US-ASCII
69
+ string: ''
70
+ headers:
71
+ User-Agent:
72
+ - Faraday v1.0.1
73
+ Accept-Encoding:
74
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
75
+ Accept:
76
+ - "*/*"
77
+ response:
78
+ status:
79
+ code: 200
80
+ message: OK
81
+ headers:
82
+ Date:
83
+ - Thu, 24 Sep 2020 15:03:35 GMT
84
+ Content-Type:
85
+ - application/json
86
+ Content-Length:
87
+ - '1011'
88
+ Connection:
89
+ - keep-alive
90
+ Server:
91
+ - Apache
92
+ Status:
93
+ - 200 OK
94
+ Content-Security-Policy:
95
+ - 'default-src ''self'' ''unsafe-inline'' blob: data: *.jortt.nl; script-src
96
+ ''self'' ''unsafe-eval'' blob: ''unsafe-inline'' files.jortt.nl *.googletagmanager.com
97
+ *.uservoice.com inlinemanual.com *.google-analytics.com *.googleadservices.com
98
+ bat.bing.com tapfiliate.com static.ads-twitter.com tagmanager.google.com analytics.twitter.com
99
+ https://connect.facebook.net https://app.inlinemanual.com; connect-src
100
+ ''self'' https://*.jortt.nl wss://*.jortt.nl analytics.inlinemanual.com files.jortt.nl
101
+ www.google-analytics.com stats.g.doubleclick.net file-storage-app-production.s3.eu-central-1.amazonaws.com
102
+ https://app.inlinemanual.com; style-src ''self'' ''unsafe-inline'' fonts.googleapis.com
103
+ files.jortt.nl tagmanager.google.com https://app.inlinemanual.com; font-src
104
+ ''self'' data: fonts.gstatic.com files.jortt.nl https://app.inlinemanual.com; frame-src
105
+ ''self'' *.jortt.nl files.jortt.nl b.frstre.com beacon.tapfiliate.com jortt.uservoice.com
106
+ *.vimeo.com https://connect.facebook.net; img-src ''self'' blob: data:
107
+ *.jortt.nl https://www.facebook.com files.jortt.nl www.google-analytics.com
108
+ stats.g.doubleclick.net www.google.nl www.google.com bat.bing.com googleads.g.doubleclick.net
109
+ https://www.googletagmanager.com https://widget.uservoice.com www.google.de
110
+ t.co *.gstatic.com https://ssl.google-analytics.com https://app.inlinemanual.com'
111
+ body:
112
+ encoding: UTF-8
113
+ string: '{"data":[{"ledger_account_id":"05a59e27-489f-466d-adf7-fc06f576d4ec","parent_ledger_account_id":"105ea7d7-8bb5-499e-9823-8324826b6563","name":"Omzet","selectable":false},{"ledger_account_id":"fcabf6bf-cccc-4a6d-b04e-7b2369d04a79","parent_ledger_account_id":"05a59e27-489f-466d-adf7-fc06f576d4ec","name":"Diverse
114
+ omzet","selectable":true},{"ledger_account_id":"05ba2a61-a0cc-4736-9000-89fb361e85c8","parent_ledger_account_id":"05a59e27-489f-466d-adf7-fc06f576d4ec","name":"Omzet
115
+ uit facturen","selectable":true},{"ledger_account_id":"92cb5ad4-e2e7-4c41-8e17-bf7db69c7b9a","parent_ledger_account_id":"986e5b45-dae6-48cc-b4c9-a2f30fbd7bfe","name":"Inkoopkosten","selectable":false},{"ledger_account_id":"424d222d-f8cb-4d38-82c0-24674a2dcf75","parent_ledger_account_id":"92cb5ad4-e2e7-4c41-8e17-bf7db69c7b9a","name":"Inkoop","selectable":true},{"ledger_account_id":"a5c08fb4-0a22-4f53-9ee2-d7682bba10f7","parent_ledger_account_id":"92cb5ad4-e2e7-4c41-8e17-bf7db69c7b9a","name":"Uitbesteed
116
+ werk","selectable":true}]}'
117
+ recorded_at: Thu, 24 Sep 2020 15:03:35 GMT
118
+ recorded_with: VCR 6.0.0
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jortt::Client::Customers, :vcr do
4
+ let(:client) { Jortt.client(ENV['JORTT_CLIENT_ID'], ENV['JORTT_CLIENT_SECRET']) }
5
+
6
+ let(:params) do
7
+ {
8
+ is_private: false,
9
+ customer_name: 'Nuka-Cola Corporation',
10
+ address_street: 'Vault 11',
11
+ address_postal_code: '1111AA',
12
+ address_city: 'Mojave Wasteland'
13
+ }
14
+ end
15
+
16
+ let!(:jane) { client.customers.create(is_private: true, customer_name: 'Jane Doe')['id'] }
17
+ let!(:john) { client.customers.create(is_private: true, customer_name: 'John Doe')['id'] }
18
+
19
+ after do
20
+ client.customers.delete(jane)
21
+ client.customers.delete(john)
22
+ end
23
+
24
+ describe '#index' do
25
+ context 'without params' do
26
+ subject { client.customers.index.to_a }
27
+
28
+ it "returns customers" do
29
+ expect(subject.count).to eq(3)
30
+ expect(subject[0]['customer_name']).to eq('Jane Doe')
31
+ expect(subject[1]['customer_name']).to eq('John Doe')
32
+ expect(subject[2]['customer_name']).to eq('Search target')
33
+ end
34
+ end
35
+
36
+ context 'query' do
37
+ subject { client.customers.index(query: 'Search target') }
38
+
39
+ it "returns the queried customers" do
40
+ expect(subject.count).to eq(1)
41
+ expect(subject.first['customer_name']).to eq("Search target")
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#show' do
47
+ subject { client.customers.show(jane) }
48
+
49
+ it "returns the customer" do
50
+ expect(subject['customer_name']).to eq("Jane Doe")
51
+ end
52
+ end
53
+
54
+ describe '#create' do
55
+ context "valid payload" do
56
+ subject { client.customers.create(params) }
57
+ after { client.customers.delete(subject['id']) }
58
+
59
+ it "creates the customer" do
60
+ uuid_length = 36
61
+ expect(subject['id'].length).to eq(uuid_length)
62
+ end
63
+ end
64
+
65
+ context "faulty payload" do
66
+ subject { client.customers.create({}) }
67
+
68
+ it "shows a nice error" do
69
+ expect { subject }.to raise_error(Jortt::Client::Error)
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#update' do
75
+ let(:uuid) { client.customers.create(params).fetch('id') }
76
+ subject { client.customers.update(uuid, params.merge(address_extra_information: 'Extra...')) }
77
+ after { client.customers.delete(uuid) }
78
+
79
+ it "updates the customer" do
80
+ expect(subject).to eq(true)
81
+ end
82
+ end
83
+
84
+ describe '#delete' do
85
+ let(:uuid) { client.customers.create(params).fetch('id') }
86
+ subject { client.customers.delete(uuid) }
87
+
88
+ it "deletes the customer" do
89
+ expect(subject).to eq(true)
90
+ end
91
+ end
92
+
93
+ describe '#direct_debit_mandate' do
94
+ subject { client.customers.direct_debit_mandate(jane) }
95
+
96
+ it "sends direct debit mandate to the customer or responds with an error when not possible" do
97
+ begin
98
+ subject
99
+ rescue Jortt::Client::Error => e
100
+ expect(e.details.first['key']).to eq("DirectDebit::NotEnabled")
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jortt::Client::Invoices, :vcr do
4
+ let(:client) { Jortt.client(ENV['JORTT_CLIENT_ID'], ENV['JORTT_CLIENT_SECRET']) }
5
+
6
+ let(:customer) { client.customers.index(query: 'Search target').first }
7
+
8
+ let(:params) do
9
+ {
10
+ customer_id: customer.fetch('id'),
11
+ send_method: 'self',
12
+ line_items: [{
13
+ vat: 21,
14
+ amount_per_unit: {
15
+ value: 499,
16
+ currency: 'EUR'
17
+ },
18
+ units: 4,
19
+ description: 'Your product'
20
+ }]
21
+ }
22
+ end
23
+
24
+ describe '#index' do
25
+ context 'pagination', vcr: false do
26
+ subject { client.invoices.index }
27
+
28
+ before do
29
+ VCR.turn_off!
30
+
31
+ stub_request(:any, "https://app.jortt.nl/oauth-provider/oauth/token").
32
+ to_return(
33
+ headers: {content_type: 'application/json'},
34
+ body: {access_token: 'abc'}.to_json)
35
+
36
+ stub_request(:get, "https://api.jortt.nl/invoices?invoice_status&page=1&query").
37
+ to_return(
38
+ headers: {content_type: 'application/json'},
39
+ body: {
40
+ 'data': [{id: 1}, {id: 2}],
41
+ _links: {next: "https://api.jortt.nl/invoices?page=2"}
42
+ }.to_json
43
+ )
44
+
45
+ stub_request(:get, "https://api.jortt.nl/invoices?invoice_status&page=2&query").
46
+ to_return(
47
+ headers: {content_type: 'application/json'},
48
+ body: {
49
+ data: [{id: 3}, {id: 4}],
50
+ _links: {next: "https://api.jortt.nl/invoices?page=3"}
51
+ }.to_json
52
+ )
53
+
54
+ stub_request(:get, "https://api.jortt.nl/invoices?invoice_status&page=3&query").
55
+ to_return(
56
+ headers: {content_type: 'application/json'},
57
+ body: {
58
+ data: [{id: 5}],
59
+ _links: {next: nil}
60
+ }.to_json
61
+ )
62
+ end
63
+
64
+ after { VCR.turn_on! }
65
+
66
+ it "returns the first page" do
67
+ expect(subject.first.fetch('id')).to eq(1)
68
+ end
69
+
70
+ it "seamlessly returns results from the other pages" do
71
+ expect(subject.to_a.count).to eq(5)
72
+ end
73
+ end
74
+
75
+ context 'invoice_status' do
76
+ subject { client.invoices.index(invoice_status: 'sent') }
77
+
78
+ it "returns those invoices" do
79
+ expect(subject.count).to be > 0
80
+ expect(subject.first.fetch('invoice_status')).to eq('sent')
81
+ end
82
+ end
83
+
84
+ context 'query' do
85
+ subject { client.invoices.index(query: 'Search target') }
86
+
87
+ it "returns the queried invoices" do
88
+ expect(subject.first.dig('invoice_due_amount', 'value')).to eq("2415.16")
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#create' do
94
+ subject { client.invoices.create(params) }
95
+
96
+ it "creates the invoice" do
97
+ uuid_length = 36
98
+ expect(subject['id'].length).to eq(uuid_length)
99
+ end
100
+ end
101
+
102
+ describe '#show' do
103
+ let(:uuid) { client.invoices.index(query: 'Search target').first.fetch('id') }
104
+ subject { client.invoices.show(uuid) }
105
+
106
+ it "returns the invoice" do
107
+ expect(subject.dig('invoice_due_amount', 'value')).to eq("2415.16")
108
+ end
109
+ end
110
+
111
+ describe '#download' do
112
+ let(:uuid) { client.invoices.index(query: 'Download test').first.fetch('id') }
113
+ subject { client.invoices.download(uuid) }
114
+
115
+ it "returns the invoice download link" do
116
+ expect(subject.fetch('download_location')).to match(/https:\/\/files\.jortt\.nl\/.*/)
117
+ end
118
+ end
119
+
120
+ describe '#credit' do
121
+ let(:uuid) { client.invoices.index(query: 'Search target').first.fetch('id') }
122
+ subject { client.invoices.credit(uuid, {send_method: 'self'}) }
123
+
124
+ it "credits the invoice" do
125
+ uuid_length = 36
126
+ expect(subject['id'].length).to eq(uuid_length)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jortt::Client::LedgerAccounts, :vcr do
4
+ let(:client) { Jortt.client(ENV['JORTT_CLIENT_ID'], ENV['JORTT_CLIENT_SECRET']) }
5
+
6
+ describe '#index' do
7
+ subject { client.ledger_accounts.index }
8
+
9
+ it "returns invoices" do
10
+ expect(subject.count).to be > 0
11
+ expect(subject.first).to eq(
12
+ "ledger_account_id" => "05a59e27-489f-466d-adf7-fc06f576d4ec",
13
+ "name" => "Omzet",
14
+ "parent_ledger_account_id" => "105ea7d7-8bb5-499e-9823-8324826b6563",
15
+ "selectable" => false
16
+ )
17
+ end
18
+ end
19
+ end
@@ -1,43 +1,22 @@
1
- # encoding: UTF-8
2
1
  require 'spec_helper'
3
2
 
4
- describe Jortt::Client do
5
- describe '#initialize' do
6
- subject { described_class.new(opts) }
7
- let(:opts) { {} }
8
-
9
- specify { expect { subject }.to raise_error(KeyError) }
10
-
11
- context 'given app_name' do
12
- before { opts[:app_name] = 'name' }
13
-
14
- specify { expect { subject }.to raise_error(KeyError) }
15
-
16
- context 'and api_key' do
17
- before { opts[:api_key] = 'secret' }
18
- it { should be_instance_of(described_class) }
19
- its(:base_url) { should eq(described_class::BASE_URL) }
20
- its(:app_name) { should eq('name') }
21
- its(:api_key) { should eq('secret') }
22
- end
23
- end
24
- end
25
-
3
+ describe Jortt::Client, :vcr do
26
4
  context 'configured' do
27
- let(:client) { described_class.new(app_name: 'app', api_key: 'secret') }
5
+ let(:client) { described_class.new(ENV['JORTT_CLIENT_ID'], ENV['JORTT_CLIENT_SECRET']) }
28
6
 
29
7
  describe '#customers' do
30
8
  subject { client.customers }
31
- it { should be_instance_of(described_class::Resource) }
32
- its(:singular) { should eq(:customer) }
33
- its(:plural) { should eq(:customers) }
9
+ it { should be_instance_of(described_class::Customers) }
34
10
  end
35
11
 
36
12
  describe '#invoices' do
37
13
  subject { client.invoices }
38
- it { should be_instance_of(described_class::Resource) }
39
- its(:singular) { should eq(:invoice) }
40
- its(:plural) { should eq(:invoices) }
14
+ it { should be_instance_of(described_class::Invoices) }
15
+ end
16
+
17
+ describe '#ledger_accounts' do
18
+ subject { client.ledger_accounts }
19
+ it { should be_instance_of(described_class::LedgerAccounts) }
41
20
  end
42
21
  end
43
22
  end
@@ -1,9 +1,8 @@
1
- # encoding: UTF-8
2
1
  require 'spec_helper'
3
2
 
4
- describe Jortt do
3
+ describe Jortt, :vcr do
5
4
  describe '.client' do
6
- subject { described_class.client(app_name: 'name', api_key: 'secret') }
5
+ subject { described_class.client(ENV['JORTT_CLIENT_ID'], ENV['JORTT_CLIENT_SECRET']) }
7
6
  it { should be_instance_of(described_class::Client) }
8
7
  end
9
8
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  require 'simplecov'
2
+ require 'rspec'
3
+ require 'rspec/its'
4
+ require 'webmock/rspec'
5
+ require 'vcr'
6
+ require 'jortt'
2
7
 
3
8
  SimpleCov.start
4
9
  if ENV['CI'] == 'true'
@@ -6,8 +11,17 @@ if ENV['CI'] == 'true'
6
11
  SimpleCov.formatter = SimpleCov::Formatter::Codecov
7
12
  end
8
13
 
9
- require 'rspec'
10
- require 'rspec/its'
11
- require 'webmock/rspec'
14
+ VCR.configure do |c|
15
+ c.cassette_library_dir = "spec/fixtures/vcr_cassettes"
16
+ c.hook_into :webmock
17
+ c.configure_rspec_metadata!
18
+ c.default_cassette_options = { record: :once }
12
19
 
13
- require 'jortt'
20
+ c.before_record do |i|
21
+ i.response.headers.delete('Set-Cookie')
22
+ i.request.headers.delete('Authorization')
23
+ end
24
+ end
25
+
26
+ ENV['JORTT_CLIENT_ID'] ||= 'client-id'
27
+ ENV['JORTT_CLIENT_SECRET'] ||= 'client-secret'