papierkram_api_client 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1a03790a5079d46fc57b6efa84682046fbfd4f4e916e68fd9e4132863dc07c3
4
- data.tar.gz: b6edd7e886bcaf9a9f761fec07494c2f6e292f77b946e0fc2f2ee33b8228d60e
3
+ metadata.gz: 77097da5dce8525d4a7919296181df43b34d6bf19cb56c200b154dfce3248e48
4
+ data.tar.gz: 8afcef52acb835ad559c9e8ff8f3ea50c87b463006a4f444428c6cee9cb74615
5
5
  SHA512:
6
- metadata.gz: 299c6bcf0f35da94d1e1e6298f2aee5cc70b4eaddc3abe2e36fd051a3286290f9182f87331debc8c79f4ddca429f4fbb14aa4a95c0276fa857177165ab7ac36f
7
- data.tar.gz: df625c5ce0e31b68b4ebcbd80e681d58674396843c43f5631544891b6e8eeeef1e788d19b38930e3cd4555755444b5e7430ebee7610df2550d22225d136df2b5
6
+ metadata.gz: 3118ca30193f803e5b200793575e980aaa8999b2fcd03109cb2ad9027dae64b4d8e5f635bf77164e0d90b400727476e0e877d61167f6aa97fa1a143c8765d6ef
7
+ data.tar.gz: e0c0a77efebb42ceb71dc478e3d4d106783bce3c4d29335ef34a93254a089a5e8453bbe5edd10a1ccfb105bebdae03b9213f7d0ee2c52d155fead33fb8417171
data/.rubocop.yml CHANGED
@@ -33,6 +33,7 @@ Metrics/ParameterLists:
33
33
  - "lib/api/v1/**/*"
34
34
 
35
35
  Metrics/ClassLength:
36
+ Max: 150
36
37
  CountAsOne:
37
38
  - "array"
38
39
  - "hash"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0] - 2023-09-10
4
+
5
+ ### Changes (BREAKING! ⚠️)
6
+
7
+ - [#63](https://github.com/simonneutert/papierkram_api_client/pull/63) Cleaner abstraction for the API client to return a certain item by id. [@simonneutert](https://github.com/simonneutert)
8
+
9
+ ### Added
10
+
11
+ - [#61](https://github.com/simonneutert/papierkram_api_client/pull/61) Adds ENV to make Minitest pass ([follow Alice](https://github.com/ordinaryzelig/minispec-metadata/pull/18)). [@simonneutert](https://github.com/simonneutert)
12
+ - [#55](https://github.com/simonneutert/papierkram_api_client/pull/55) Adds missing chapter for Transactions. [@simonneutert](https://github.com/simonneutert)
13
+
14
+ ## [0.2.4] - 2023-06-30
15
+
16
+ ### Fixed
17
+
18
+ - [#48](https://github.com/simonneutert/papierkram_api_client/pull/48) Arguments weren't truly optional when possible. [@simonneutert](https://github.com/simonneutert)
19
+
3
20
  [0.2.3] - 2023-06-29
4
21
 
5
22
  ### Added
data/Gemfile CHANGED
@@ -5,12 +5,13 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in papierkram_api_client.gemspec
6
6
  gemspec
7
7
 
8
- gem 'minitest', '~> 5.18'
8
+ gem 'minitest', '~> 5.17'
9
9
  gem 'minitest-vcr', '~> 1.4'
10
10
  gem 'pry', '~> 0.14.2'
11
11
  gem 'rake', '~> 13.0'
12
- gem 'rubocop', '~> 1.53', require: false
12
+ gem 'rubocop', '~> 1.56', require: false
13
13
  gem 'rubocop-minitest', '~> 0.31.0', require: false
14
- gem 'rubocop-performance', '~> 1.18', require: false
14
+ gem 'rubocop-performance', '~> 1.19', require: false
15
15
  gem 'rubocop-rake', '~> 0.6.0', require: false
16
16
  gem 'vcr', '~> 6.2'
17
+ gem 'webmock', '~> 3.19'
data/Gemfile.lock CHANGED
@@ -1,28 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- papierkram_api_client (0.2.3)
4
+ papierkram_api_client (0.3.0)
5
5
  faraday (~> 2.7)
6
6
  httpx (>= 0.22.5, < 0.25.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
+ addressable (2.8.5)
12
+ public_suffix (>= 2.0.2, < 6.0)
11
13
  ast (2.4.2)
14
+ base64 (0.1.1)
12
15
  coderay (1.1.3)
13
- faraday (2.7.7)
16
+ crack (0.4.5)
17
+ rexml
18
+ faraday (2.7.10)
14
19
  faraday-net_http (>= 2.0, < 3.1)
15
20
  ruby2_keywords (>= 0.0.4)
16
21
  faraday-net_http (3.0.2)
22
+ hashdiff (1.0.1)
17
23
  http-2-next (0.5.1)
18
- httpx (0.24.0)
24
+ httpx (0.24.4)
19
25
  http-2-next (>= 0.4.1)
20
26
  json (2.6.3)
21
27
  language_server-protocol (3.17.0.3)
22
28
  method_source (1.0.0)
23
29
  minispec-metadata (2.0.0)
24
30
  minitest
25
- minitest (5.18.1)
31
+ minitest (5.20.0)
26
32
  minitest-vcr (1.4.0)
27
33
  minispec-metadata (~> 2.0)
28
34
  minitest (>= 4.7.5)
@@ -34,12 +40,14 @@ GEM
34
40
  pry (0.14.2)
35
41
  coderay (~> 1.1)
36
42
  method_source (~> 1.0)
43
+ public_suffix (5.0.3)
37
44
  racc (1.7.1)
38
45
  rainbow (3.1.1)
39
46
  rake (13.0.6)
40
47
  regexp_parser (2.8.1)
41
- rexml (3.2.5)
42
- rubocop (1.53.1)
48
+ rexml (3.2.6)
49
+ rubocop (1.56.2)
50
+ base64 (~> 0.1.1)
43
51
  json (~> 2.3)
44
52
  language_server-protocol (>= 3.17.0)
45
53
  parallel (~> 1.10)
@@ -47,14 +55,14 @@ GEM
47
55
  rainbow (>= 2.2.2, < 4.0)
48
56
  regexp_parser (>= 1.8, < 3.0)
49
57
  rexml (>= 3.2.5, < 4.0)
50
- rubocop-ast (>= 1.28.0, < 2.0)
58
+ rubocop-ast (>= 1.28.1, < 2.0)
51
59
  ruby-progressbar (~> 1.7)
52
60
  unicode-display_width (>= 2.4.0, < 3.0)
53
61
  rubocop-ast (1.29.0)
54
62
  parser (>= 3.2.1.0)
55
- rubocop-minitest (0.31.0)
63
+ rubocop-minitest (0.31.1)
56
64
  rubocop (>= 1.39, < 2.0)
57
- rubocop-performance (1.18.0)
65
+ rubocop-performance (1.19.0)
58
66
  rubocop (>= 1.7.0, < 2.0)
59
67
  rubocop-ast (>= 0.4.0)
60
68
  rubocop-rake (0.6.0)
@@ -63,6 +71,10 @@ GEM
63
71
  ruby2_keywords (0.0.5)
64
72
  unicode-display_width (2.4.2)
65
73
  vcr (6.2.0)
74
+ webmock (3.19.1)
75
+ addressable (>= 2.8.0)
76
+ crack (>= 0.3.2)
77
+ hashdiff (>= 0.4.0, < 2.0.0)
66
78
 
67
79
  PLATFORMS
68
80
  arm64-darwin-22
@@ -70,16 +82,17 @@ PLATFORMS
70
82
  x86_64-linux
71
83
 
72
84
  DEPENDENCIES
73
- minitest (~> 5.18)
85
+ minitest (~> 5.17)
74
86
  minitest-vcr (~> 1.4)
75
87
  papierkram_api_client!
76
88
  pry (~> 0.14.2)
77
89
  rake (~> 13.0)
78
- rubocop (~> 1.53)
90
+ rubocop (~> 1.56)
79
91
  rubocop-minitest (~> 0.31.0)
80
- rubocop-performance (~> 1.18)
92
+ rubocop-performance (~> 1.19)
81
93
  rubocop-rake (~> 0.6.0)
82
94
  vcr (~> 6.2)
95
+ webmock (~> 3.19)
83
96
 
84
97
  BUNDLED WITH
85
- 2.4.12
98
+ 2.4.19
data/README.md CHANGED
@@ -10,10 +10,6 @@ Der erste ~~illegale~~ inoffizielle API Client in [Ruby](https://www.ruby-lang.o
10
10
 
11
11
  ---
12
12
 
13
- Hol mehr aus deinen Daten raus! Dieser Client bietet dir bald einige Features im Bereich [Business Intelligence](#business-intelligence)!
14
-
15
- ---
16
-
17
13
  **WERBUNG** (es ist ein Aufruf zur Mitarbeit 🫠)
18
14
  JETZT NEU! Ohne Lack und frei von Glamour!
19
15
  Das Gleiche, nur in grün, also für [NodeJS](https://github.com/simonneutert/papierkram-api-client). Und als Mega-Baustelle 😬
@@ -24,16 +20,16 @@ Das Gleiche, nur in grün, also für [NodeJS](https://github.com/simonneutert/pa
24
20
 
25
21
  > 🚨 **Bitte beachte**, dass DU UNBEDINGT die Requests/Responses der VCR Cassettes (die ausschliesslich bei Nutzung der Testsuite angelegt werden) von privaten Daten befreien musst, bevor du einen Pull Request erstellst oder einen Commit ins Web lädst! Ich werde die Cassettes auch nochmal durchgehen, bevor ich die Version 1.0.0 veröffentliche. ABER BITTE, BITTE, BITTE, mach das selbst auch! Ich habe keine Lust, dass irgendwelche Daten von dir oder deinen Kunden auf Github landen. Danke! 🙏
26
22
 
27
- Check das [CHANGELOG.md](CHANGELOG.md), Baby!
23
+ Check das [CHANGELOG.md](CHANGELOG.md), Baby!
24
+ Schau in [UPGRADING.md](UPGRADING.md), 💃🕺!
28
25
 
29
26
  Hier geht es zu den [offiziellen API Docs](https://demo.papierkram.de/api/v1/api-docs/index.html).
30
- Schau bitte dort um alle Rückgabefelder/-werte zu checken, bis ich die Dokumentation hier komplett habe.
27
+ Schau bitte dort um alle Rückgabefelder/-werte zu checken, bis ich (oder du mit deiner Zeit und Hingabe) die Dokumentation hier komplett habe.
31
28
 
32
29
  ---
33
30
 
34
31
  ## Aktuell unterstützte Endpunkte der Papierkram API (V1)<!-- omit in toc -->
35
32
 
36
-
37
33
  - [x] Banking::BankConnection
38
34
  - [x] Banking::BankTransaction
39
35
  - [x] Contact::Company (Unternehmen)
@@ -66,6 +62,8 @@ Ziele:
66
62
  - [alle Bankverbindungen](#alle-bankverbindungen)
67
63
  - [eine Bankverbindung](#eine-bankverbindung)
68
64
  - [Banking::Transaction (Kontoumsatz)](#bankingtransaction-kontoumsatz)
65
+ - [alle Kontoumsätze einer Bankverbindung](#alle-kontoumsätze-einer-bankverbindung)
66
+ - [einen Kontoumsatz](#einen-kontoumsatz)
69
67
  - [Contact::Company (Unternehmen)](#contactcompany-unternehmen)
70
68
  - [alle Unternehmen](#alle-unternehmen)
71
69
  - [ein Unternehmen](#ein-unternehmen)
@@ -226,7 +224,7 @@ puts bank_connections.body
226
224
  #### eine Bankverbindung
227
225
 
228
226
  ```ruby
229
- bank_connection = client.banking_bank_connections.by(id: 1)
227
+ bank_connection = client.banking_bank_connections.find_by(id: 1)
230
228
  puts bank_connection.headers
231
229
  puts bank_connection.body
232
230
  ```
@@ -263,9 +261,28 @@ puts bank_connection.body
263
261
 
264
262
  ### Banking::Transaction (Kontoumsatz)
265
263
 
266
- WORK IN PROGRESS
264
+ Der Endpunkt `/papierkram_api/v1/endpoints/banking/transactions` liefert Informationen über die Kontoumsätze. Die Informationen werden als `Faraday::Response` zurückgegeben.
267
265
 
268
- [Transactions](lib/papierkram_api/v1/endpoints/banking/transactions.rb)
266
+ Siehe [Transactions](lib/papierkram_api/v1/endpoints/banking/transactions.rb) für mögliche Parameter.
267
+
268
+ #### alle Kontoumsätze einer Bankverbindung
269
+
270
+ ```ruby
271
+ bank_connection_id = 4
272
+ transactions = client.banking_transactions.all(bank_connection_id: bank_connection_id,
273
+ page: 1,
274
+ page_size: 2)
275
+ puts transactions.headers
276
+ puts transactions.body
277
+ ```
278
+
279
+ #### einen Kontoumsatz
280
+
281
+ ```ruby
282
+ transactions = client.banking_transactions.find_by(id: bank_connection_id)
283
+ puts transactions.headers
284
+ puts transactions.body
285
+ ```
269
286
 
270
287
  ### Contact::Company (Unternehmen)
271
288
 
@@ -284,7 +301,7 @@ puts companies.body
284
301
  #### ein Unternehmen
285
302
 
286
303
  ```ruby
287
- company = client.contact_companies.by(id: 1)
304
+ company = client.contact_companies.find_by(id: 1)
288
305
  puts company.headers
289
306
  puts company.body
290
307
  ```
@@ -355,7 +372,7 @@ puts companies.body
355
372
  #### eine Kontaktperson (eines Unternehmens)
356
373
 
357
374
  ```ruby
358
- company = client.contact_companies_persons.by(company_id: 1, id: 1)
375
+ company = client.contact_companies_persons.find_by(company_id: 1, id: 1)
359
376
  puts company.headers
360
377
  puts company.body
361
378
  ```
@@ -412,7 +429,7 @@ puts vouchers.body
412
429
  #### einen Ausgabe Beleg
413
430
 
414
431
  ```ruby
415
- voucher = client.expense_vouchers.by(id: 1)
432
+ voucher = client.expense_vouchers.find_by(id: 1)
416
433
  puts voucher.headers
417
434
  puts voucher.body
418
435
  ```
@@ -420,7 +437,7 @@ puts voucher.body
420
437
  #### einen Ausgabe Beleg als PDF
421
438
 
422
439
  ```ruby
423
- voucher = client.expense_vouchers.by(id: 1, pdf: true)
440
+ voucher = client.expense_vouchers.find_by(id: 1, pdf: true)
424
441
  puts PapierkramApi::V1::Helpers::PdfFromResponse.new(voucher).to_pdf
425
442
  # => {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}
426
443
  ```
@@ -442,7 +459,7 @@ puts estimates.body
442
459
  #### ein Angebot
443
460
 
444
461
  ```ruby
445
- estimate = client.income_estimates.by(id: 1)
462
+ estimate = client.income_estimates.find_by(id: 1)
446
463
  puts estimate.headers
447
464
  puts estimate.body
448
465
  ```
@@ -450,7 +467,7 @@ puts estimate.body
450
467
  #### ein Angebot als PDF
451
468
 
452
469
  ```ruby
453
- estimate = client.income_estimates.by(id: 1, pdf: true)
470
+ estimate = client.income_estimates.find_by(id: 1, pdf: true)
454
471
  puts PapierkramApi::V1::Helpers::PdfFromResponse.new(estimate).to_pdf
455
472
  # => {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}
456
473
  ```
@@ -472,7 +489,7 @@ puts invoices.body
472
489
  #### eine Rechnung
473
490
 
474
491
  ```ruby
475
- invoice = client.income_invoices.by(id: 1)
492
+ invoice = client.income_invoices.find_by(id: 1)
476
493
  puts invoice.headers
477
494
  puts invoice.body
478
495
  ```
@@ -480,7 +497,7 @@ puts invoice.body
480
497
  #### eine Rechnung als PDF
481
498
 
482
499
  ```ruby
483
- invoice = client.income_invoices.by(id: 1, pdf: true)
500
+ invoice = client.income_invoices.find_by(id: 1, pdf: true)
484
501
  puts PapierkramApi::V1::Helpers::PdfFromResponse.new(invoice).to_pdf
485
502
  # => {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}
486
503
  ```
@@ -502,7 +519,7 @@ puts propositions.body
502
519
  #### eine Ware / Dienstleistung
503
520
 
504
521
  ```ruby
505
- proposition = client.income_propositions.by(id: 1)
522
+ proposition = client.income_propositions.find_by(id: 1)
506
523
  puts proposition.headers
507
524
  puts proposition.body
508
525
  ```
@@ -586,7 +603,7 @@ puts projects.body
586
603
  #### ein Projekt
587
604
 
588
605
  ```ruby
589
- project = client.projects.by(id: 1)
606
+ project = client.projects.find_by(id: 1)
590
607
  puts project.headers
591
608
  puts project.body
592
609
  ```
@@ -652,7 +669,7 @@ puts tasks.body
652
669
  #### eine Aufgabe
653
670
 
654
671
  ```ruby
655
- task = client.tracker_tasks.by(id: 1)
672
+ task = client.tracker_tasks.find_by(id: 1)
656
673
  puts task.headers
657
674
  puts task.body
658
675
  ```
@@ -674,7 +691,7 @@ puts time_entries.body
674
691
  #### einen Zeiteintrag
675
692
 
676
693
  ```ruby
677
- time_entry = client.tracker_time_entries.by(id: 1)
694
+ time_entry = client.tracker_time_entries.find_by(id: 1)
678
695
  puts time_entry.headers
679
696
  puts time_entry.body
680
697
  ```
@@ -697,6 +714,8 @@ quota = client.info.remaining_quota(response)
697
714
 
698
715
  ## Business Intelligence
699
716
 
717
+ Ich lasse diesen ersten Ausflug in Auswertungen erstmal hier im Gem. Aber sollte ich die Zeit finden und weitere KPIs wichtig finden, dann gehören die Auswertungen eigentlich in ein eigenes Package.
718
+
700
719
  TODO ergänzen wie man `SmartQueries` erstellt und verwendet.
701
720
  TODO ergänzen wie man `SmartQueries` funktioneren.
702
721
  TODO ergänzen wie die Rückgabewerte von `SmartQueries` gestaltet werden sollten.
@@ -787,7 +806,7 @@ Unterstützte Endpunkte sind beispielsweise: `Income::Estimate`, `Income::Invoic
787
806
  [Api::V1::Helpers::PdfFromResponse](lib/papierkram_api/v1/helper/pdf_from_response.rb)
788
807
 
789
808
  ```ruby
790
- response = client.income_invoices.by(id: 1, pdf: true)
809
+ response = client.income_invoices.find_by(id: 1, pdf: true)
791
810
  pdf = PapierkramApi::V1::Helpers::PdfFromResponse.new(response).to_pdf("Rechnung Nummer XXX")
792
811
  puts pdf
793
812
  ```
data/UPGRADING.md ADDED
@@ -0,0 +1,8 @@
1
+ ## From 0.2 to 0.3
2
+
3
+ Finding specific records has changed. Instead of `by(id: 123)` you now use `find_by(id: 123)`.
4
+
5
+ ```ruby
6
+ banking_transaction = client.banking_transactions.find_by(id: 123)
7
+ ```
8
+
@@ -24,7 +24,7 @@ module PapierkramApi
24
24
 
25
25
  def collect_expense_vouchers
26
26
  all_expense_vouchers_in_date_range.map do |voucher|
27
- @expense_voucher_api.by(id: voucher['id']).body
27
+ @expense_voucher_api.find_by(id: voucher['id']).body
28
28
  end
29
29
  end
30
30
 
@@ -49,7 +49,7 @@ module PapierkramApi
49
49
  end
50
50
 
51
51
  def expense_voucher(id)
52
- @expense_voucher_api.by(id: id)
52
+ @expense_voucher_api.find_by(id: id)
53
53
  end
54
54
  end
55
55
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../base'
4
+
3
5
  module PapierkramApi
4
6
  module V1
5
7
  module Endpoints
6
8
  module Banking
7
9
  # This class is responsible for all the API calls related to banking bank connections.
8
10
  class BankConnections < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/banking/bank_connections/#{id}")
11
+ def find_by(id:)
12
+ http_get("#{@url_api_path}/banking/bank_connections/#{id}")
11
13
  end
12
14
 
13
15
  def all(page: 1,
@@ -21,7 +23,7 @@ module PapierkramApi
21
23
  query[:order_by] = order_by if order_by
22
24
  query[:order_direction] = order_direction if order_direction
23
25
 
24
- get("#{@url_api_path}/banking/bank_connections", query)
26
+ http_get("#{@url_api_path}/banking/bank_connections", query)
25
27
  end
26
28
  end
27
29
  end
@@ -6,8 +6,8 @@ module PapierkramApi
6
6
  module Banking
7
7
  # This class is responsible for all the API calls related to banking transactions.
8
8
  class Transactions < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/banking/transactions/#{id}")
9
+ def find_by(id:)
10
+ http_get("#{@url_api_path}/banking/transactions/#{id}")
11
11
  end
12
12
 
13
13
  def all(bank_connection_id:,
@@ -23,7 +23,7 @@ module PapierkramApi
23
23
  query[:order_by] = order_by if order_by
24
24
  query[:order_direction] = order_direction if order_direction
25
25
 
26
- get("#{@url_api_path}/banking/transactions", query)
26
+ http_get("#{@url_api_path}/banking/transactions", query)
27
27
  end
28
28
  end
29
29
  end
@@ -22,24 +22,24 @@ module PapierkramApi
22
22
  raise ArgumentError, "No remaining quota found in response: #{response}"
23
23
  end
24
24
 
25
- def get(url, params = {}, headers = {})
25
+ def http_get(url, params = {}, headers = {})
26
26
  validate_get!(params)
27
27
  call_wrapper!(:get, url, params, headers)
28
28
  end
29
29
 
30
- def post(url, params = {}, headers = {})
30
+ def http_post(url, params = {}, headers = {})
31
31
  call_wrapper!(:post, url, params, headers)
32
32
  end
33
33
 
34
- def put(url, params = {}, headers = {})
34
+ def http_put(url, params = {}, headers = {})
35
35
  call_wrapper!(:put, url, params, headers)
36
36
  end
37
37
 
38
- def patch(url, params = {}, headers = {})
38
+ def http_patch(url, params = {}, headers = {})
39
39
  call_wrapper!(:patch, url, params, headers)
40
40
  end
41
41
 
42
- def delete(url, params = {}, headers = {})
42
+ def http_delete(url, params = {}, headers = {})
43
43
  call_wrapper!(:delete, url, params, headers)
44
44
  end
45
45
 
@@ -6,8 +6,8 @@ module PapierkramApi
6
6
  module Contact
7
7
  # This class is responsible for all the API calls related to banking bank connections.
8
8
  class Companies < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/contact/companies/#{id}")
9
+ def find_by(id:)
10
+ http_get("#{@url_api_path}/contact/companies/#{id}")
11
11
  end
12
12
 
13
13
  def all(page: 1,
@@ -21,10 +21,10 @@ module PapierkramApi
21
21
  query[:order_by] = order_by if order_by
22
22
  query[:order_direction] = order_direction if order_direction
23
23
 
24
- get("#{@url_api_path}/contact/companies", query)
24
+ http_get("#{@url_api_path}/contact/companies", query)
25
25
  end
26
26
 
27
- def create_supplier( # rubocop:disable Metrics/ParameterLists
27
+ def create_supplier( # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
28
  name:,
29
29
  phone: nil,
30
30
  fax: nil,
@@ -50,37 +50,36 @@ module PapierkramApi
50
50
  color: nil
51
51
  )
52
52
 
53
- body = {
54
- contact_type: :supplier,
55
- name: name,
56
- phone: phone,
57
- fax: fax,
58
- email: email,
59
- delivery_method: delivery_method,
60
- ust_idnr: ust_idnr,
61
- website: website,
62
- twitter: twitter,
63
- postal_street: postal_street,
64
- postal_city: postal_city,
65
- postal_zip: postal_zip,
66
- postal_country: postal_country,
67
- physical_street: physical_street,
68
- physical_city: physical_city,
69
- physical_zip: physical_zip,
70
- physical_country: physical_country,
71
- bank_blz: bank_blz,
72
- bank_institute: bank_institute,
73
- bank_account_no: bank_account_no,
74
- bank_bic: bank_bic,
75
- bank_iban: bank_iban,
76
- notes: notes,
77
- color: color
78
- }
79
-
80
- post("#{@url_api_path}/contact/companies", body)
53
+ body = {}
54
+ body[:contact_type] = 'supplier'
55
+ body[:name] = name
56
+ body[:phone] = phone if phone
57
+ body[:fax] = fax if fax
58
+ body[:email] = email if email
59
+ body[:delivery_method] = delivery_method if delivery_method
60
+ body[:ust_idnr] = ust_idnr if ust_idnr
61
+ body[:website] = website if website
62
+ body[:twitter] = twitter if twitter
63
+ body[:postal_street] = postal_street if postal_street
64
+ body[:postal_city] = postal_city if postal_city
65
+ body[:postal_zip] = postal_zip if postal_zip
66
+ body[:postal_country] = postal_country if postal_country
67
+ body[:physical_street] = physical_street if physical_street
68
+ body[:physical_city] = physical_city if physical_city
69
+ body[:physical_zip] = physical_zip if physical_zip
70
+ body[:physical_country] = physical_country if physical_country
71
+ body[:bank_blz] = bank_blz if bank_blz
72
+ body[:bank_institute] = bank_institute if bank_institute
73
+ body[:bank_account_no] = bank_account_no if bank_account_no
74
+ body[:bank_bic] = bank_bic if bank_bic
75
+ body[:bank_iban] = bank_iban if bank_iban
76
+ body[:notes] = notes if notes
77
+ body[:color] = color if color
78
+
79
+ http_post("#{@url_api_path}/contact/companies", body)
81
80
  end
82
81
 
83
- def create_customer( # rubocop:disable Metrics/ParameterLists
82
+ def create_customer( # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
84
83
  name:,
85
84
  phone: nil,
86
85
  fax: nil,
@@ -106,59 +105,58 @@ module PapierkramApi
106
105
  color: nil
107
106
  )
108
107
 
109
- body = {
110
- contact_type: :customer,
111
- name: name,
112
- phone: phone,
113
- fax: fax,
114
- email: email,
115
- delivery_method: delivery_method,
116
- ust_idnr: ust_idnr,
117
- website: website,
118
- twitter: twitter,
119
- postal_street: postal_street,
120
- postal_city: postal_city,
121
- postal_zip: postal_zip,
122
- postal_country: postal_country,
123
- physical_street: physical_street,
124
- physical_city: physical_city,
125
- physical_zip: physical_zip,
126
- physical_country: physical_country,
127
- bank_blz: bank_blz,
128
- bank_institute: bank_institute,
129
- bank_account_no: bank_account_no,
130
- bank_bic: bank_bic,
131
- bank_iban: bank_iban,
132
- notes: notes,
133
- color: color
134
- }
135
-
136
- post("#{@url_api_path}/contact/companies", body)
108
+ body = {}
109
+ body[:contact_type] = 'customer'
110
+ body[:name] = name
111
+ body[:phone] = phone if phone
112
+ body[:fax] = fax if fax
113
+ body[:email] = email if email
114
+ body[:delivery_method] = delivery_method if delivery_method
115
+ body[:ust_idnr] = ust_idnr if ust_idnr
116
+ body[:website] = website if website
117
+ body[:twitter] = twitter if twitter
118
+ body[:postal_street] = postal_street if postal_street
119
+ body[:postal_city] = postal_city if postal_city
120
+ body[:postal_zip] = postal_zip if postal_zip
121
+ body[:postal_country] = postal_country if postal_country
122
+ body[:physical_street] = physical_street if physical_street
123
+ body[:physical_city] = physical_city if physical_city
124
+ body[:physical_zip] = physical_zip if physical_zip
125
+ body[:physical_country] = physical_country if physical_country
126
+ body[:bank_blz] = bank_blz if bank_blz
127
+ body[:bank_institute] = bank_institute if bank_institute
128
+ body[:bank_account_no] = bank_account_no if bank_account_no
129
+ body[:bank_bic] = bank_bic if bank_bic
130
+ body[:bank_iban] = bank_iban if bank_iban
131
+ body[:notes] = notes if notes
132
+ body[:color] = color if color
133
+
134
+ http_post("#{@url_api_path}/contact/companies", body)
137
135
  end
138
136
 
139
137
  def update_by(id:, attributes: {})
140
138
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
141
139
  raise ArgumentError, 'attributes must be a Hash' unless attributes.is_a?(Hash)
142
140
 
143
- put("#{@url_api_path}/contact/companies/#{id}", attributes)
141
+ http_put("#{@url_api_path}/contact/companies/#{id}", attributes)
144
142
  end
145
143
 
146
144
  def delete_by(id:)
147
145
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
148
146
 
149
- delete("#{@url_api_path}/contact/companies/#{id}")
147
+ http_delete("#{@url_api_path}/contact/companies/#{id}")
150
148
  end
151
149
 
152
150
  def archive_by(id:)
153
151
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
154
152
 
155
- post("#{@url_api_path}/contact/companies/#{id}/archive")
153
+ http_post("#{@url_api_path}/contact/companies/#{id}/archive")
156
154
  end
157
155
 
158
156
  def unarchive_by(id:)
159
157
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
160
158
 
161
- post("#{@url_api_path}/contact/companies/#{id}/unarchive")
159
+ http_post("#{@url_api_path}/contact/companies/#{id}/unarchive")
162
160
  end
163
161
  end
164
162
  end
@@ -6,8 +6,8 @@ module PapierkramApi
6
6
  module Contact
7
7
  # This class is responsible for all the API calls related to companies' persons connections.
8
8
  class CompaniesPersons < PapierkramApi::V1::Endpoints::Base
9
- def by(company_id:, id:)
10
- get("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}")
9
+ def find_by(company_id:, id:)
10
+ http_get("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}")
11
11
  end
12
12
 
13
13
  def all(company_id:, page: 1, page_size: 100, order_by: nil, order_direction: nil)
@@ -19,10 +19,10 @@ module PapierkramApi
19
19
  query[:order_by] = order_by if order_by
20
20
  query[:order_direction] = order_direction if order_direction
21
21
 
22
- get("#{@url_api_path}/contact/companies/#{company_id}/persons", query)
22
+ http_get("#{@url_api_path}/contact/companies/#{company_id}/persons", query)
23
23
  end
24
24
 
25
- def create( # rubocop:disable Metrics/ParameterLists
25
+ def create( # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
26
26
  company_id:,
27
27
  first_name:,
28
28
  last_name:,
@@ -37,22 +37,21 @@ module PapierkramApi
37
37
  skype: nil,
38
38
  comment: nil
39
39
  )
40
- body = {
41
- first_name: first_name,
42
- last_name: last_name,
43
- title: title,
44
- salutation: salutation,
45
- position: position,
46
- department: department,
47
- email: email,
48
- phone: phone,
49
- mobile: mobile,
50
- fax: fax,
51
- skype: skype,
52
- comment: comment
53
- }
40
+ body = {}
41
+ body[:first_name] = first_name
42
+ body[:last_name] = last_name
43
+ body[:title] = title if title
44
+ body[:salutation] = salutation if salutation
45
+ body[:position] = position if position
46
+ body[:department] = department if department
47
+ body[:email] = email if email
48
+ body[:phone] = phone if phone
49
+ body[:mobile] = mobile if mobile
50
+ body[:fax] = fax if fax
51
+ body[:skype] = skype if skype
52
+ body[:comment] = comment if comment
54
53
 
55
- post("#{@url_api_path}/contact/companies/#{company_id}/persons", body)
54
+ http_post("#{@url_api_path}/contact/companies/#{company_id}/persons", body)
56
55
  end
57
56
 
58
57
  def update_by(company_id:, id:, attributes: {})
@@ -60,14 +59,14 @@ module PapierkramApi
60
59
  raise ArgumentError, 'company_id must be an Integer' unless company_id.is_a?(Integer)
61
60
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
62
61
 
63
- put("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}", attributes)
62
+ http_put("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}", attributes)
64
63
  end
65
64
 
66
65
  def delete_by(company_id:, id:)
67
66
  raise ArgumentError, 'company_id must be an Integer' unless company_id.is_a?(Integer)
68
67
  raise ArgumentError, 'id must be an Integer' unless id.is_a?(Integer)
69
68
 
70
- delete("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}")
69
+ http_delete("#{@url_api_path}/contact/companies/#{company_id}/persons/#{id}")
71
70
  end
72
71
  end
73
72
  end
@@ -6,12 +6,12 @@ module PapierkramApi
6
6
  module Expense
7
7
  # This class is responsible for all the API calls related to expense vouchers.
8
8
  class Vouchers < PapierkramApi::V1::Endpoints::Base
9
- def by(id:, pdf: false)
9
+ def find_by(id:, pdf: false)
10
10
  if pdf == true
11
11
  return get("#{@url_api_path}/expense/vouchers/#{id}/pdf", nil,
12
12
  { headers: { 'Content-Type' => 'application/pdf' } })
13
13
  end
14
- get("#{@url_api_path}/expense/vouchers/#{id}")
14
+ http_get("#{@url_api_path}/expense/vouchers/#{id}")
15
15
  end
16
16
 
17
17
  def all(page: 1, # rubocop:disable Metrics/CyclomaticComplexity
@@ -36,7 +36,7 @@ module PapierkramApi
36
36
  document_date_range_end
37
37
  end
38
38
 
39
- get("#{@url_api_path}/expense/vouchers", query)
39
+ http_get("#{@url_api_path}/expense/vouchers", query)
40
40
  end
41
41
  end
42
42
  end
@@ -6,13 +6,16 @@ module PapierkramApi
6
6
  module Income
7
7
  # This class is responsible for all the API calls related to income estimates.
8
8
  class Estimates < PapierkramApi::V1::Endpoints::Base
9
- def by(id:, pdf: false)
9
+ def find_by(id:, pdf: false)
10
10
  if pdf == true
11
- return get("#{@url_api_path}/income/estimates/#{id}/pdf", nil,
12
- { headers: { 'Content-Type' => 'application/pdf' } })
11
+ return http_get(
12
+ "#{@url_api_path}/income/estimates/#{id}/pdf",
13
+ nil,
14
+ { headers: { 'Content-Type' => 'application/pdf' } }
15
+ )
13
16
  end
14
17
 
15
- get("#{@url_api_path}/income/estimates/#{id}")
18
+ http_get("#{@url_api_path}/income/estimates/#{id}")
16
19
  end
17
20
 
18
21
  def all(page: 1, # rubocop:disable Metrics/CyclomaticComplexity
@@ -37,7 +40,7 @@ module PapierkramApi
37
40
  document_date_range_end
38
41
  end
39
42
 
40
- get("#{@url_api_path}/income/estimates", query)
43
+ http_get("#{@url_api_path}/income/estimates", query)
41
44
  end
42
45
  end
43
46
  end
@@ -6,13 +6,16 @@ module PapierkramApi
6
6
  module Income
7
7
  # This class is responsible for all the API calls related to income invoices.
8
8
  class Invoices < PapierkramApi::V1::Endpoints::Base
9
- def by(id:, pdf: false)
9
+ def find_by(id:, pdf: false)
10
10
  if pdf == true
11
- return get("#{@url_api_path}/income/invoices/#{id}/pdf", nil,
12
- { headers: { 'Content-Type' => 'application/pdf' } })
11
+ return http_get(
12
+ "#{@url_api_path}/income/invoices/#{id}/pdf",
13
+ nil,
14
+ { headers: { 'Content-Type' => 'application/pdf' } }
15
+ )
13
16
  end
14
17
 
15
- get("#{@url_api_path}/income/invoices/#{id}")
18
+ http_get("#{@url_api_path}/income/invoices/#{id}")
16
19
  end
17
20
 
18
21
  def all(page: 1, # rubocop:disable Metrics/CyclomaticComplexity
@@ -37,7 +40,7 @@ module PapierkramApi
37
40
  document_date_range_end
38
41
  end
39
42
 
40
- get("#{@url_api_path}/income/invoices", query)
43
+ http_get("#{@url_api_path}/income/invoices", query)
41
44
  end
42
45
  end
43
46
  end
@@ -6,12 +6,12 @@ module PapierkramApi
6
6
  module Income
7
7
  # This class is responsible for all the API calls related to income propositions.
8
8
  class Propositions < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/income/propositions/#{id}")
9
+ def find_by(id:)
10
+ http_get("#{@url_api_path}/income/propositions/#{id}")
11
11
  end
12
12
 
13
13
  def all
14
- get("#{@url_api_path}/income/propositions")
14
+ http_get("#{@url_api_path}/income/propositions")
15
15
  end
16
16
 
17
17
  def create(
@@ -21,40 +21,39 @@ module PapierkramApi
21
21
  time_unit: nil,
22
22
  proposition_type: nil,
23
23
  price: nil,
24
- vat_rate: ''
24
+ vat_rate: nil
25
25
  )
26
- body = {
27
- name: name,
28
- article_no: article_no,
29
- description: description,
30
- time_unit: time_unit,
31
- proposition_type: proposition_type,
32
- price: price,
33
- vat_rate: vat_rate
34
- }
35
- post("#{@url_api_path}/income/propositions", body)
26
+
27
+ body = {}
28
+ body[:name] = name
29
+ body[:article_no] = article_no
30
+ body[:description] = description if description
31
+ body[:time_unit] = time_unit if time_unit
32
+ body[:proposition_type] = proposition_type if proposition_type
33
+ body[:price] = price if price
34
+ body[:vat_rate] = vat_rate if vat_rate
35
+
36
+ http_post("#{@url_api_path}/income/propositions", body)
36
37
  end
37
38
 
38
39
  def update_by(id:, attributes: {})
39
- attributes[:vat_rate] ||= attributes['vat_rate']
40
- attributes[:vat_rate] ||= ''
41
- if attributes[:vat_rate].empty? || !attributes[:vat_rate].include?('%')
40
+ if attributes[:vat_rate] && (attributes[:vat_rate].empty? || !attributes[:vat_rate].include?('%'))
42
41
  raise ArgumentError, 'vat_rate must be a percentage and include a % sign'
43
42
  end
44
43
 
45
- put("#{@url_api_path}/income/propositions/#{id}", attributes)
44
+ http_put("#{@url_api_path}/income/propositions/#{id}", attributes)
46
45
  end
47
46
 
48
47
  def delete_by(id:)
49
- delete("#{@url_api_path}/income/propositions/#{id}")
48
+ http_delete("#{@url_api_path}/income/propositions/#{id}")
50
49
  end
51
50
 
52
51
  def archive_by(id:)
53
- post("#{@url_api_path}/income/propositions/#{id}/archive")
52
+ http_post("#{@url_api_path}/income/propositions/#{id}/archive")
54
53
  end
55
54
 
56
55
  def unarchive_by(id:)
57
- post("#{@url_api_path}/income/propositions/#{id}/unarchive")
56
+ http_post("#{@url_api_path}/income/propositions/#{id}/unarchive")
58
57
  end
59
58
  end
60
59
  end
@@ -6,7 +6,7 @@ module PapierkramApi
6
6
  # This class is responsible for all the API calls related to info connections.
7
7
  class Info < PapierkramApi::V1::Endpoints::Base
8
8
  def details
9
- get("#{@url_api_path}/info")
9
+ http_get("#{@url_api_path}/info")
10
10
  end
11
11
  end
12
12
  end
@@ -5,8 +5,8 @@ module PapierkramApi
5
5
  module Endpoints
6
6
  # This class is responsible for all the API calls related to projects connections.
7
7
  class Projects < PapierkramApi::V1::Endpoints::Base
8
- def by(id:)
9
- get("#{@url_api_path}/projects/#{id}")
8
+ def find_by(id:)
9
+ http_get("#{@url_api_path}/projects/#{id}")
10
10
  end
11
11
 
12
12
  def all(page: 1, per_page: 100, order_by: nil, order_direction: nil, company_id: nil)
@@ -18,10 +18,10 @@ module PapierkramApi
18
18
  query[:order_direction] = order_direction if order_direction
19
19
  query[:company_id] = company_id if company_id
20
20
 
21
- get("#{@url_api_path}/projects", query)
21
+ http_get("#{@url_api_path}/projects", query)
22
22
  end
23
23
 
24
- def create( # rubocop:disable Metrics/ParameterLists
24
+ def create( # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
25
25
  name:,
26
26
  customer_id:,
27
27
  description: nil,
@@ -33,44 +33,44 @@ module PapierkramApi
33
33
  budget_time: nil,
34
34
  budget_time_unit: nil,
35
35
  color: nil,
36
- default_proposition: {},
37
- team_members: []
36
+ default_proposition: nil,
37
+ team_members: nil
38
38
  )
39
- body = {
40
- name: name,
41
- description: description,
42
- start_date: start_date,
43
- end_date: end_date,
44
- flagged: flagged,
45
- budget_type: budget_type,
46
- budget_money: budget_money,
47
- budget_time: budget_time,
48
- budget_time_unit: budget_time_unit,
49
- color: color,
50
- customer: { id: customer_id },
51
- default_proposition: default_proposition,
52
- team_members: team_members
53
- }
54
39
 
55
- post("#{@url_api_path}/projects", body)
40
+ body = {}
41
+ body[:name] = name
42
+ body[:customer] = { id: customer_id }
43
+ body[:description] = description if description
44
+ body[:start_date] = start_date if start_date
45
+ body[:end_date] = end_date if end_date
46
+ body[:flagged] = flagged if flagged
47
+ body[:budget_type] = budget_type if budget_type
48
+ body[:budget_money] = budget_money if budget_money
49
+ body[:budget_time] = budget_time if budget_time
50
+ body[:budget_time_unit] = budget_time_unit if budget_time_unit
51
+ body[:color] = color if color
52
+ body[:default_proposition] = default_proposition if default_proposition
53
+ body[:team_members] = team_members if team_members
54
+
55
+ http_post("#{@url_api_path}/projects", body)
56
56
  end
57
57
 
58
58
  def update_by(id:, attributes: {})
59
59
  raise ArgumentError, 'attributes must be a Hash' unless attributes.is_a?(Hash)
60
60
 
61
- put("#{@url_api_path}/projects/#{id}", attributes)
61
+ http_put("#{@url_api_path}/projects/#{id}", attributes)
62
62
  end
63
63
 
64
64
  def delete_by(id:)
65
- delete("#{@url_api_path}/projects/#{id}")
65
+ http_delete("#{@url_api_path}/projects/#{id}")
66
66
  end
67
67
 
68
68
  def archive_by(id:)
69
- post("#{@url_api_path}/projects/#{id}/archive")
69
+ http_post("#{@url_api_path}/projects/#{id}/archive")
70
70
  end
71
71
 
72
72
  def unarchive_by(id:)
73
- post("#{@url_api_path}/projects/#{id}/unarchive")
73
+ http_post("#{@url_api_path}/projects/#{id}/unarchive")
74
74
  end
75
75
  end
76
76
  end
@@ -6,8 +6,8 @@ module PapierkramApi
6
6
  module Tracker
7
7
  # This class is responsible for all the API calls related to tracker tasks connections.
8
8
  class Tasks < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/tracker/tasks/#{id}")
9
+ def find_by(id:)
10
+ http_get("#{@url_api_path}/tracker/tasks/#{id}")
11
11
  end
12
12
 
13
13
  def all(page: 1,
@@ -24,7 +24,7 @@ module PapierkramApi
24
24
  query[:order_direction] = order_direction if order_direction
25
25
  query[:project_id] = project_id if project_id
26
26
  query[:proposition_id] = proposition_id if proposition_id
27
- get("#{@url_api_path}/tracker/tasks", query)
27
+ http_get("#{@url_api_path}/tracker/tasks", query)
28
28
  end
29
29
  end
30
30
  end
@@ -6,8 +6,8 @@ module PapierkramApi
6
6
  module Tracker
7
7
  # This class is responsible for all the API calls related to tracker time entries connections.
8
8
  class TimeEntries < PapierkramApi::V1::Endpoints::Base
9
- def by(id:)
10
- get("#{@url_api_path}/tracker/time_entries/#{id}")
9
+ def find_by(id:)
10
+ http_get("#{@url_api_path}/tracker/time_entries/#{id}")
11
11
  end
12
12
 
13
13
  def all(page: 1, # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/ParameterLists
@@ -38,7 +38,8 @@ module PapierkramApi
38
38
  query[:billing_state] = billing_state if billing_state
39
39
  query[:start_time_range_start] = start_time_range_start if start_time_range_start
40
40
  query[:start_time_range_end] = start_time_range_end if start_time_range_end
41
- get("#{@url_api_path}/tracker/time_entries", query)
41
+
42
+ http_get("#{@url_api_path}/tracker/time_entries", query)
42
43
  end
43
44
 
44
45
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PapierkramApiClient
4
- VERSION = '0.2.3'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papierkram_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Neutert
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-29 00:00:00.000000000 Z
11
+ date: 2023-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -63,6 +63,7 @@ files:
63
63
  - LICENSE.txt
64
64
  - README.md
65
65
  - Rakefile
66
+ - UPGRADING.md
66
67
  - lib/papierkram_api/client.rb
67
68
  - lib/papierkram_api/v1/business_intelligence/base.rb
68
69
  - lib/papierkram_api/v1/business_intelligence/expenses_by_category.rb
@@ -111,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  - !ruby/object:Gem::Version
112
113
  version: '0'
113
114
  requirements: []
114
- rubygems_version: 3.4.14
115
+ rubygems_version: 3.4.13
115
116
  signing_key:
116
117
  specification_version: 4
117
118
  summary: Papierkram API Client