{"id":15594888,"url":"https://github.com/simonneutert/papierkram_api_client","last_synced_at":"2025-04-10T04:43:10.019Z","repository":{"id":152739785,"uuid":"626999319","full_name":"simonneutert/papierkram_api_client","owner":"simonneutert","description":"Ruby Client für die Papierkram.de API","archived":false,"fork":false,"pushed_at":"2025-04-02T18:51:21.000Z","size":348,"stargazers_count":3,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-02T19:40:14.756Z","etag":null,"topics":["api","client","papierkram","rest-api","ruby"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/papierkram_api_client","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonneutert.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-12T15:22:35.000Z","updated_at":"2025-04-02T18:51:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"ea39debe-aba7-483a-a731-77b65d9fc650","html_url":"https://github.com/simonneutert/papierkram_api_client","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2Fpapierkram_api_client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2Fpapierkram_api_client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2Fpapierkram_api_client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2Fpapierkram_api_client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonneutert","download_url":"https://codeload.github.com/simonneutert/papierkram_api_client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248161231,"owners_count":21057552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","client","papierkram","rest-api","ruby"],"created_at":"2024-10-03T00:42:02.842Z","updated_at":"2025-04-10T04:43:09.991Z","avatar_url":"https://github.com/simonneutert.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Papierkram API Client\u003c!-- omit in toc --\u003e\n\n[![Ruby](https://github.com/simonneutert/papierkram_api_client/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/simonneutert/papierkram_api_client/actions/workflows/main.yml)\n\nDer erste ~~illegale~~ inoffizielle API Client in [Ruby](https://www.ruby-lang.org/de/) für [Papierkram.de](https://www.papierkram.de) als [Gem](https://rubygems.org/gems/papierkram_api_client) für dein Projekt!\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.svg\" alt=\"PAC Logo, Zunge leckt an Karl Klammer und zieht Daten aus dem Papierkram-Account wie Frosch die Fliege vom Teich\" width=\"300\"\u003e\n\u003c/div\u003e\n\n---\n\n**Aufruf zur Mitarbeit für NodeJS/JavaScript 🫠**  \nDas Gleiche, nur in grün, also für [NodeJS ein Papierkram Api Client](https://github.com/simonneutert/papierkram-api-client) 😬\n\n---\n\n**WICHTIG** Dieses Projekt befindet sich im Entwicklungsstatus bis V1.0.0! Ich werde versuchen, die Änderungen so gut wie möglich zu dokumentieren. Wenn du einen Fehler findest, kannst du gerne einen Issue erstellen oder einen Pull Request mit einer Verbesserung erstellen. Ich freue mich über jede Hilfe!\n\n\u003e 🚨 **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! 🙏\n\nCheck das [CHANGELOG.md](CHANGELOG.md), Baby!  \nSchau in [UPGRADING.md](UPGRADING.md), 💃🕺!\n\nHier geht es zu den [offiziellen API Docs](https://demo.papierkram.de/api/v1/api-docs/index.html).  \nSchau bitte dort um alle Rückgabefelder/-werte zu checken, bis ich (oder du mit deiner Zeit und Hingabe) die Dokumentation hier komplett habe.\n\n**WENN DU PROBLEME HAST,** bitte ich dich erstmal die [offiziellen API Docs](https://demo.papierkram.de/api/v1/api-docs/index.html) zu durchstöbern. Dann lohnt es sich hier die Beispiele (weiter unten) zu lesen und von dort sowohl mal in die Methoden im Code zu springen, oder noch besser in die Tests schauen.  \nWenn du dann immer noch nicht weiterkommst, kannst du gerne einen Issue erstellen. Poste dabei so viele Informationen wie möglich, damit ich dir bestmöglich weiterhelfen kann. Achte dabei bitte darauf, dass du keine privaten Daten postest. 🙏\n\n---\n\n## Aktuell unterstützte Endpunkte der Papierkram API (V1)\u003c!-- omit in toc --\u003e\n\n- [x] Banking::BankConnection\n- [x] Banking::BankTransaction\n- [x] Contact::Company (Unternehmen)\n- [x] Contact::Company (Kontaktpersonen)\n- [x] Expense::Voucher (Ausgabe Belege)\n- [x] Income::Estimate (Angebote)\n- [x] Income::Invoice (Rechnungen)\n- [x] Income::PaymentTerms (Zahlungsbedingungen)\n- [x] Income::Proposition (Waren / Dienstleistungen)\n- [x] Info\n- [ ] Settings::CustomAttribute (Datenfelder)\n- [x] Project (Projekte)\n- [x] Tracker::Task (Aufgaben)\n- [x] Tracker::TimeEntry (Zeiterfassung)\n- [ ] User\n\n## Was, wie, warum?\u003c!-- omit in toc --\u003e\n\nPapierkram.de hat nun eine API Schnittstelle für die Programmierung von eigenen Anwendungen. Die Dokumentation dazu findest du [hier](https://demo.papierkram.de/papierkram_api/v1/api-docs/index.html).\n\nZiele:\n\n- Rückgabe von Hashes, Arrays, etc. statt von komplexeren Objekten (der gefürchtete DIY-Ansatz).\n- Einfach zu testen und zu erweitern.\n\n---\n\n- [Installation](#installation)\n- [Schnellstart](#schnellstart)\n- [API Client](#api-client)\n  - [Initialisierung](#initialisierung)\n  - [Banking::BankConnection (Bankverbindung)](#bankingbankconnection-bankverbindung)\n    - [alle Bankverbindungen](#alle-bankverbindungen)\n    - [eine Bankverbindung](#eine-bankverbindung)\n  - [Banking::Transaction (Kontoumsatz)](#bankingtransaction-kontoumsatz)\n    - [alle Kontoumsätze einer Bankverbindung](#alle-kontoumsätze-einer-bankverbindung)\n    - [einen Kontoumsatz](#einen-kontoumsatz)\n  - [Contact::Company (Unternehmen)](#contactcompany-unternehmen)\n    - [alle Unternehmen](#alle-unternehmen)\n    - [ein Unternehmen](#ein-unternehmen)\n    - [erstelle ein Unternehmen](#erstelle-ein-unternehmen)\n    - [aktualisiere ein Unternehmen](#aktualisiere-ein-unternehmen)\n    - [lösche ein Unternehmen](#lösche-ein-unternehmen)\n    - [archiviere ein Unternehmen](#archiviere-ein-unternehmen)\n    - [unarchiviere ein Unternehmen](#unarchiviere-ein-unternehmen)\n  - [Contact::Company (Kontaktperson eines Unternehmens)](#contactcompany-kontaktperson-eines-unternehmens)\n    - [alle Kontaktpersonen (eines Unternehmens)](#alle-kontaktpersonen-eines-unternehmens)\n    - [eine Kontaktperson (eines Unternehmens)](#eine-kontaktperson-eines-unternehmens)\n    - [erstelle eine Kontaktperson (eines Unternehmens)](#erstelle-eine-kontaktperson-eines-unternehmens)\n    - [aktualisiere eine Kontaktperson (eines Unternehmens)](#aktualisiere-eine-kontaktperson-eines-unternehmens)\n    - [lösche eine Kontaktperson (eines Unternehmens)](#lösche-eine-kontaktperson-eines-unternehmens)\n  - [Expense::Voucher (Ausgabe Beleg)](#expensevoucher-ausgabe-beleg)\n    - [alle Ausgabe Belege](#alle-ausgabe-belege)\n    - [einen Ausgabe Beleg](#einen-ausgabe-beleg)\n    - [einen Ausgabe Beleg als PDF](#einen-ausgabe-beleg-als-pdf)\n    - [einen Ausgabe Beleg erstellen](#einen-ausgabe-beleg-erstellen)\n    - [einen Ausgabe Beleg aktualisieren](#einen-ausgabe-beleg-aktualisieren)\n    - [einen Ausgabe Beleg löschen](#einen-ausgabe-beleg-löschen)\n    - [einen Ausgabe Beleg archivieren](#einen-ausgabe-beleg-archivieren)\n    - [einen Ausgabe Beleg unarchivieren](#einen-ausgabe-beleg-unarchivieren)\n    - [einen Ausgabe Beleg stornieren](#einen-ausgabe-beleg-stornieren)\n    - [einen Ausgabe Beleg rückwirkend stornieren](#einen-ausgabe-beleg-rückwirkend-stornieren)\n    - [einen Ausgabe Beleg als bezahlt markieren](#einen-ausgabe-beleg-als-bezahlt-markieren)\n    - [einem Ausgabe Beleg ein Dokument hinzufügen](#einem-ausgabe-beleg-ein-dokument-hinzufügen)\n    - [einem Ausgabe Beleg ein Dokument entfernen](#einem-ausgabe-beleg-ein-dokument-entfernen)\n  - [Income::Estimate (Angebot)](#incomeestimate-angebot)\n    - [alle Angebote](#alle-angebote)\n    - [ein Angebot](#ein-angebot)\n    - [ein Angebot als PDF](#ein-angebot-als-pdf)\n  - [Income::Invoice (Rechnung)](#incomeinvoice-rechnung)\n    - [alle Rechnungen](#alle-rechnungen)\n    - [eine Rechnung](#eine-rechnung)\n    - [eine Rechnung als PDF](#eine-rechnung-als-pdf)\n    - [eine Rechnung erstellen](#eine-rechnung-erstellen)\n    - [eine Rechnung aktualisieren](#eine-rechnung-aktualisieren)\n    - [eine Rechnung löschen](#eine-rechnung-löschen)\n    - [eine Rechnung archivieren](#eine-rechnung-archivieren)\n    - [eine Rechnung unarchivieren](#eine-rechnung-unarchivieren)\n    - [eine Rechnung stornieren](#eine-rechnung-stornieren)\n    - [eine Rechnung verschicken](#eine-rechnung-verschicken)\n  - [Income::PaymentTerms (Zahlungsbedingungen)](#incomepaymentterms-zahlungsbedingungen)\n    - [eine Zahlungsbedingung](#eine-zahlungsbedingung)\n    - [alle Zahlungsbedingungen](#alle-zahlungsbedingungen)\n  - [Income::Proposition (Waren / Dienstleistungen)](#incomeproposition-waren--dienstleistungen)\n    - [alle Waren / Dienstleistungen](#alle-waren--dienstleistungen)\n    - [eine Ware / Dienstleistung](#eine-ware--dienstleistung)\n    - [eine Ware / Dienstleistung erstellen](#eine-ware--dienstleistung-erstellen)\n    - [eine Ware / Dienstleistung aktualisieren](#eine-ware--dienstleistung-aktualisieren)\n    - [eine Ware / Dienstleistung löschen](#eine-ware--dienstleistung-löschen)\n    - [eine Ware / Dienstleistung archivieren](#eine-ware--dienstleistung-archivieren)\n    - [eine Ware / Dienstleistung unarchivieren](#eine-ware--dienstleistung-unarchivieren)\n  - [Info](#info)\n  - [Project::Project (Projekt)](#projectproject-projekt)\n    - [alle Projekte](#alle-projekte)\n    - [ein Projekt](#ein-projekt)\n    - [erstelle ein Projekt](#erstelle-ein-projekt)\n    - [aktualisiere ein Projekt](#aktualisiere-ein-projekt)\n    - [lösche ein Projekt](#lösche-ein-projekt)\n    - [archiviere ein Projekt](#archiviere-ein-projekt)\n    - [unarchiviere ein Projekt](#unarchiviere-ein-projekt)\n  - [Tracker::Task (Aufgabe)](#trackertask-aufgabe)\n    - [alle Aufgaben](#alle-aufgaben)\n    - [eine Aufgabe](#eine-aufgabe)\n    - [erstelle eine Aufgabe](#erstelle-eine-aufgabe)\n    - [aktualisiere eine Aufgabe](#aktualisiere-eine-aufgabe)\n    - [lösche eine Aufgabe](#lösche-eine-aufgabe)\n    - [archiviere eine Aufgabe](#archiviere-eine-aufgabe)\n    - [unarchiviere eine Aufgabe](#unarchiviere-eine-aufgabe)\n  - [Tracker::TimeEntry (Zeiteintrag)](#trackertimeentry-zeiteintrag)\n    - [alle Zeiteinträge](#alle-zeiteinträge)\n    - [einen Zeiteintrag](#einen-zeiteintrag)\n    - [erstelle einen Zeiteintrag](#erstelle-einen-zeiteintrag)\n    - [aktualisiere einen Zeiteintrag](#aktualisiere-einen-zeiteintrag)\n    - [lösche einen Zeiteintrag](#lösche-einen-zeiteintrag)\n    - [archiviere einen Zeiteintrag](#archiviere-einen-zeiteintrag)\n    - [unarchiviere einen Zeiteintrag](#unarchiviere-einen-zeiteintrag)\n  - [Verbleibendes Quota](#verbleibendes-quota)\n- [Business Intelligence](#business-intelligence)\n  - [Business::Intelligence (BI) ExpenseByCategory (Ausgaben nach Kategorie)](#businessintelligence-bi-expensebycategory-ausgaben-nach-kategorie)\n    - [alle Ausgaben eines Monats nach Kategorie](#alle-ausgaben-eines-monats-nach-kategorie)\n    - [alle Ausgaben eines Monats nach Kategorie gefiltert nach Steuersatz](#alle-ausgaben-eines-monats-nach-kategorie-gefiltert-nach-steuersatz)\n- [Helpers](#helpers)\n  - [Generiere ein PDF aus Response](#generiere-ein-pdf-aus-response)\n- [Development / Mitentwickeln](#development--mitentwickeln)\n  - [Localhost 3000! 🤫](#localhost-3000-)\n- [Contributing](#contributing)\n- [Releasing](#releasing)\n- [License](#license)\n\n## Installation\n\nInstall the gem and add to the application's Gemfile by executing:\n\n    $ bundle add papierkram_api_client\n\nIf bundler is not being used to manage dependencies, install the gem by executing:\n\n    $ gem install papierkram_api_client\n\n## Schnellstart\n\n1. Repository klonen\n2. `bundle install`\n3. `bin/console`\n\n```ruby\n# client instanziieren\n\n# wenn ENV gesetzt sind (siehe Readme)\nclient = PapierkramApi::Client.new\n\n# ODER per Variablen\nclient = PapierkramApi::Client.new('subdomain', \"YOUR-API-KEY\");\n\n# info Endpunkt abfragen\ninfo_details = client.info.details\nputs info_details.headers\nputs info_details.body\n\n# erste Seite von \"allen Rechnungen\" abfragen\ninvoices = client.income_invoices.all(page: 1, page_size: 5)\nputs invoices.headers\nputs invoices.body\n```\n\n## API Client\n\nDer API Client ist die Hauptklasse für die Kommunikation mit der Papierkram API. Er wird mit den Zugangsdaten initialisiert.\n\n[Client](lib/papierkram_api/client.rb)\n\nWenn du etwas hinter die Kulissen sehen willst, schau dir diese [Faraday](https://github.com/lostisland/faraday) Klasse an [Faraday::Response](https://github.com/lostisland/faraday/blob/main/lib/faraday/response.rb).\n\n### Initialisierung\n\nEntweder werden die Zugangsdaten als Argumente übergeben:\n\n```ruby\n# usage with subdomain and api key\nclient = PapierkramApi::Client.new('subdomain', \"SUPER-LONG-API-KEY\")\n```\n\nOder es werden die Umgebungsvariablen `PAPIERKRAM_API_SUBDOMAIN` und `PAPIERKRAM_API_KEY` gesetzt und der Client ohne Argumente initialisiert.\n\nIch kann dir wärmstes https://direnv.net/ empfehlen, um die Umgebungsvariablen zu setzen. 🤓\n\n```ruby\n# usage with environment variables\nclient = PapierkramApi::Client.new\n```\n\n### Banking::BankConnection (Bankverbindung)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/banking/bank_connections` liefert Informationen über die Bankverbindungen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [BankConnections](lib/papierkram_api/v1/endpoints/banking/bank_connections.rb) für mögliche Parameter.\n\n#### alle Bankverbindungen\n\n```ruby\nbank_connections = client.banking_bank_connections.all\nputs bank_connections.headers\nputs bank_connections.body\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eResponse\u003c/summary\u003e\n\n```ruby\n# body\n{\n  \"type\"=\u003e\"list\",\n  \"page\"=\u003e1,\n  \"page_size\"=\u003e100,\n  \"total_pages\"=\u003e1,\n  \"total_entries\"=\u003e1,\n  \"has_more\"=\u003efalse,\n  \"entries\"=\u003e[\n    { \"type\"=\u003e\"bank_connection\",\n      \"id\"=\u003e4,\n      \"name\"=\u003e\"Standard\" }\n  ]\n}\n```\n\n\u003c/details\u003e\n\n#### eine Bankverbindung\n\n```ruby\nbank_connection = client.banking_bank_connections.find_by(id: 1)\nputs bank_connection.headers\nputs bank_connection.body\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eResponse\u003c/summary\u003e\n\n```ruby\n# body\n{\n  \"type\"=\u003e\"bank_connection\",\n  \"id\"=\u003e4,\n  \"name\"=\u003e\"Standard\",\n  \"account_no\"=\u003enil,\n  \"account_type\"=\u003e\"default\",\n  \"bic\"=\u003enil,\n  \"blz\"=\u003enil,\n  \"connection_type\"=\u003e\"default\",\n  \"created_at\"=\u003e\"2019-12-31T13:29:19.000+01:00\",\n  \"customer_id\"=\u003enil,\n  \"hbci\"=\u003enil,\n  \"hbci_host_url\"=\u003enil,\n  \"hbci_version\"=\u003enil,\n  \"primary\"=\u003enil,\n  \"title\"=\u003e\"Standard\",\n  \"updated_at\"=\u003e\"2020-11-03T10:31:56.000+01:00\",\n  \"user_id\"=\u003enil,\n  \"iban\"=\u003e\"\"\n}\n```\n\n\u003c/details\u003e\n\n### Banking::Transaction (Kontoumsatz)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/banking/transactions` liefert Informationen über die Kontoumsätze. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Transactions](lib/papierkram_api/v1/endpoints/banking/transactions.rb) für mögliche Parameter.\n\n#### alle Kontoumsätze einer Bankverbindung\n\n```ruby\nbank_connection_id = 4\ntransactions = client.banking_transactions.all(bank_connection_id: bank_connection_id,\n                                               page: 1,\n                                               page_size: 2)\nputs transactions.headers\nputs transactions.body\n```\n\n#### einen Kontoumsatz\n\n```ruby\ntransactions = client.banking_transactions.find_by(id: bank_connection_id)\nputs transactions.headers\nputs transactions.body\n```\n\n### Contact::Company (Unternehmen)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/contact/companies` liefert Informationen über die Unternehmen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Companies](lib/papierkram_api/v1/endpoints/contact/companies.rb) für mögliche Parameter.\n\n#### alle Unternehmen\n\n```ruby\ncompanies = client.contact_companies.all\nputs companies.headers\nputs companies.body\n```\n\n#### ein Unternehmen\n\n```ruby\ncompany = client.contact_companies.find_by(id: 1)\nputs company.headers\nputs company.body\n```\n\n#### erstelle ein Unternehmen\n\n```ruby\n# supplier\ncompany = client.contact_companies.create_supplier(name: 'Test GmbH')\nputs company.headers\nputs company.body\n\n# customer\ncompany = client.contact_companies.create_customer(name: 'Test GmbH')\nputs company.headers\nputs company.body\n```\n\nSiehe [Companies#create_customer](lib/papierkram_api/v1/endpoints/contact/companies.rb) und [Companies#create_supplier](lib/papierkram_api/v1/endpoints/contact/companies.rb) für mögliche Parameter.\n\n#### aktualisiere ein Unternehmen\n\n```ruby\ncompany = client.contact_companies.update_by(\n  id: 1,\n  name: 'Test GmbH'\n)\nputs company.headers\nputs company.body\n```\n\n#### lösche ein Unternehmen\n\n```ruby\ncompany = client.contact_companies.delete_by(id: 1)\nputs company.headers\nputs company.body\n```\n\n#### archiviere ein Unternehmen\n\n```ruby\ncompany = client.contact_companies.archive_by(id: 1)\nputs company.headers\nputs company.body\n```\n\n#### unarchiviere ein Unternehmen\n\n```ruby\ncompany = client.contact_companies.unarchive_by(id: 1)\nputs company.headers\nputs company.body\n```\n\n### Contact::Company (Kontaktperson eines Unternehmens)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/contact/companies/{company_id}` liefert Informationen über die Kontaktpersonen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [CompaniesPersons](lib/papierkram_api/v1/endpoints/contact/companies_persons.rb) für mögliche Parameter.\n\n#### alle Kontaktpersonen (eines Unternehmens)\n\n```ruby\ncompanies = client.contact_companies_persons.all(company_id: 1)\nputs companies.headers\nputs companies.body\n```\n\n#### eine Kontaktperson (eines Unternehmens)\n\n```ruby\ncompany = client.contact_companies_persons.find_by(company_id: 1, id: 1)\nputs company.headers\nputs company.body\n```\n\n#### erstelle eine Kontaktperson (eines Unternehmens)\n\n```ruby\ncompany = client.contact_companies_persons.create(\n  company_id: 1,\n  first_name: 'Max',\n  last_name: 'Mustermann'\n)\nputs company.headers\nputs company.body\n```\n\nSiehe [CompaniesPersons#create](lib/papierkram_api/v1/endpoints/contact/companies_persons.rb) für mögliche Parameter.\n\n#### aktualisiere eine Kontaktperson (eines Unternehmens)\n\n```ruby\ncompany = client.contact_companies_persons.update_by(\n  id: 1,\n  company_id: 1,\n  first_name: 'Moritz'\n)\nputs company.headers\nputs company.body\n```\n\nSiehe [CompaniesPersons#update_by](lib/papierkram_api/v1/endpoints/contact/companies_persons.rb) für mögliche Parameter.\n\n#### lösche eine Kontaktperson (eines Unternehmens)\n\n```ruby\ncompany = client.contact_companies_persons.delete_by(company_id: 1, id: 1)\nputs company.headers\nputs company.body\n```\n\n### Expense::Voucher (Ausgabe Beleg)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/expense/vouchers` liefert Informationen über die Ausgabe Belege. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Vouchers](lib/papierkram_api/v1/endpoints/expense/vouchers.rb) für mögliche Parameter.\n\n#### alle Ausgabe Belege\n\n```ruby\nvouchers = client.expense_vouchers.all\nputs vouchers.headers\nputs vouchers.body\n```\n\n#### einen Ausgabe Beleg\n\n```ruby\nvoucher = client.expense_vouchers.find_by(id: 1)\nputs voucher.headers\nputs voucher.body\n```\n\n#### einen Ausgabe Beleg als PDF\n\n```ruby\nvoucher = client.expense_vouchers.find_by(id: 1, pdf: true)\nputs PapierkramApi::V1::Helpers::PdfFromResponse.new(voucher).to_pdf\n# =\u003e {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}\n```\n\n#### einen Ausgabe Beleg erstellen\n\nSiehe [Vouchers#create](lib/papierkram_api/v1/endpoints/expense/vouchers.rb) für mögliche Parameter.\n\n```ruby\nvoucher = client.expense_vouchers.create(\n  name: \"Restaurant visit\",\n  due_date: \"2020-06-30\",\n  document_date: \"2020-06-14\",\n  description: \"Took customer for dinner.\",\n  entertainment_reason: \"sales meeting\",\n  flagged: true,\n  provenance: \"domestic\",\n  entertainment_persons: [\n    \"Carl Customer\"\n  ],\n  creditor_id: 85,\n  line_items: [\n    {\n      amount: 150.8,\n      name: \"restaurant bill\",\n      vat_rate: 0.19,\n      category: \"Bewirtungskosten\"\n    },\n    {\n      amount: 15,\n      name: \"tip\",\n      vat_rate: 0.19,\n      category: \"Bewirtungskosten\"\n    }\n  ]\n)\n```\n\n#### einen Ausgabe Beleg aktualisieren\n\nSiehe [Vouchers#update_by](lib/papierkram_api/v1/endpoints/expense/vouchers.rb) für mögliche Parameter.\n\n```ruby\nvoucher = client.expense_vouchers.update_by(\n  id: 1,\n  document_date: \"2020-06-13\",\n  creditor_id: 102,\n  line_items: [\n    {\n      amount: 170.8,\n      name: \"restaurant bill\",\n      vat_rate: 0.19,\n      category: \"Bewirtungskosten\",\n      billing: null,\n      depreciation: null\n    },\n    {\n      amount: 15,\n      name: \"tip\",\n      vat_rate: 0.19,\n      category: \"Bewirtungskosten\"\n    }\n  ]\n)\n```\n\n#### einen Ausgabe Beleg löschen\n\n```ruby\nvoucher = client.expense_vouchers.delete_by(id: 1)\n```\n\n#### einen Ausgabe Beleg archivieren\n\n```ruby\nvoucher = client.expense_vouchers.archive_by(id: 1)\n```\n\n#### einen Ausgabe Beleg unarchivieren\n\n```ruby\nvoucher = client.expense_vouchers.unarchive_by(id: 1)\n```\n\n#### einen Ausgabe Beleg stornieren\n\n```ruby\nvoucher = client.expense_vouchers.cancel_by(id: 1)\n```\n\n#### einen Ausgabe Beleg rückwirkend stornieren\n\n```ruby\nvoucher = client.expense_vouchers.cancel_with_reverse_entry_by(id: 1)\n```\n\n#### einen Ausgabe Beleg als bezahlt markieren\n\nSiehe [Vouchers#mark_as_paid_by](lib/papierkram_api/v1/endpoints/expense/vouchers.rb) für mögliche Parameter.\n\n```ruby\nvoucher = client.expense_vouchers.mark_as_paid_by(\n  id: 1,\n  value: 119.0\n)\n```\n\n#### einem Ausgabe Beleg ein Dokument hinzufügen\n\nSiehe [Vouchers#add_document_by](lib/papierkram_api/v1/endpoints/expense/vouchers.rb) für mögliche Parameter.\n\nUm ein PDF hinzuzufügen:\n\n```ruby\nvoucher = client.expense_vouchers.add_document_by(\n  id: 1,\n  path_to_file: 'path/to/file.pdf',\n  file_type: 'application/pdf'\n)\n```\n\noder mit einem Bild im jpeg Format\n\n```ruby\nvoucher = client.expense_vouchers.add_document_by(\n  id: 1,\n  path_to_file: 'path/to/file.jpeg',\n  file_type: 'image/jpeg'\n)\n```\n\n#### einem Ausgabe Beleg ein Dokument entfernen\n\n```ruby\nvoucher = client.expense_vouchers.delete_document_by(\n  id: 1,\n  document_id: 1\n)\n```\n\n### Income::Estimate (Angebot)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/income/estimates` liefert Informationen über die Angebote. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Estimates](lib/papierkram_api/v1/endpoints/income/estimates.rb) für mögliche Parameter.\n\n#### alle Angebote\n\n```ruby\nestimates = client.income_estimates.all\nputs estimates.headers\nputs estimates.body\n```\n\n#### ein Angebot\n\n```ruby\nestimate = client.income_estimates.find_by(id: 1)\nputs estimate.headers\nputs estimate.body\n```\n\n#### ein Angebot als PDF\n\n```ruby\nestimate = client.income_estimates.find_by(id: 1, pdf: true)\nputs PapierkramApi::V1::Helpers::PdfFromResponse.new(estimate).to_pdf\n# =\u003e {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}\n```\n\n### Income::Invoice (Rechnung)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/income/invoices` liefert Informationen über die Rechnungen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Invoices](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n#### alle Rechnungen\n\n```ruby\ninvoices = client.income_invoices.all\nputs invoices.headers\nputs invoices.body\n```\n\n#### eine Rechnung\n\n```ruby\ninvoice = client.income_invoices.find_by(id: 1)\nputs invoice.headers\nputs invoice.body\n```\n\n#### eine Rechnung als PDF\n\n```ruby\ninvoice = client.income_invoices.find_by(id: 1, pdf: true)\nputs PapierkramApi::V1::Helpers::PdfFromResponse.new(invoice).to_pdf\n# =\u003e {response: Faraday::Response, path_to_pdf_file: 'path/to/tempfile_pdf.pdf'}\n```\n\n#### eine Rechnung erstellen\n\nSiehe [Invoices#create](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\ninvoice = client.income_invoices.create(\n  name: 'Neuausstattung des Büros',\n  supply_date: '01.01.2024 - 14.01.2024',\n  document_date: '2024-01-15',\n  payment_term_id: 46,\n  customer_id: 3,\n  project_id: 15,\n  line_items: [\n    {\n      name: 'Anlieferung',\n      description: 'Anlieferung der neuen Möbel',\n      quantity: 1.25,\n      unit: 'Stunden',\n      vat_rate: 0.19,\n      price: 100\n    },\n    {\n      name: 'Bestuhlung',\n      description: 'Bestuhlung des Bürogebäudes',\n      quantity: 1.25,\n      unit: 'Arbeitstage',\n      vat_rate: 0.19,\n      price: 800\n    },\n    {\n      name: 'Büroartikel',\n      description: 'Neue Bürostühle',\n      quantity: 200,\n      unit: 'Stühle',\n      vat_rate: 0.19,\n      price: 125\n    }\n  ]\n)\n```\n\n#### eine Rechnung aktualisieren\n\nSiehe [Invoices#update_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\nresponse = client.income_invoices.update_by(\n  id: 9,\n  name: 'Neuausstattung eines Büros',\n  line_items: [\n    {\n      name: 'Anlieferung',\n      description: 'Anlieferung der neuen Möbel',\n      quantity: 1.5,\n      unit: 'Stunden',\n      vat_rate: 0.19,\n      price: 100\n    },\n    {\n      name: 'Bestuhlung',\n      description: 'Bestuhlung des Bürogebäudes',\n      quantity: 1.5,\n      unit: 'Arbeitstage',\n      vat_rate: 0.19,\n      price: 800\n    },\n    {\n      name: 'Büroartikel',\n      description: 'Neue Bürostühle',\n      quantity: 200,\n      unit: 'Stühle',\n      vat_rate: 0.19,\n      price: 125\n    }\n  ]\n)\n```\n\n#### eine Rechnung löschen\n\nSiehe [Invoices#delete_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\ninvoice = client.income_invoices.delete_by(id: 1)\n```\n\n#### eine Rechnung archivieren\n\nSiehe [Invoices#archive_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\ninvoice = client.income_invoices.archive_by(id: 1)\n```\n\n#### eine Rechnung unarchivieren\n\nSiehe [Invoices#unarchive_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\ninvoice = client.income_invoices.unarchive_by(id: 1)\n```\n\n#### eine Rechnung stornieren\n\nSiehe [Invoices#cancel_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\n```ruby\ninvoice = client.income_invoices.cancel_by(id: 1)\n```\n\n#### eine Rechnung verschicken\n\nSiehe [Invoices#send_by](lib/papierkram_api/v1/endpoints/income/invoices.rb) für mögliche Parameter.\n\nPer E-Mail:\n\n```ruby\ninvoice = client.income_invoices.deliver_by(\n  id: 1,\n  send_via: 'email',\n  email_recipient: \"test@test.test\",\n  email_subject: \"Ich verkaufe was du brauchst\",\n  email_body: \"Sag einfach was du brauchst und ich verkaufe es dir.\",\n)\n```\n\nPer PDF:\n\n```ruby\ninvoice = client.income_invoices.deliver_by(\n  id: 1,\n  send_via: 'pdf'\n)\n```\n\n### Income::PaymentTerms (Zahlungsbedingungen)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/income/payment_terms` liefert Informationen über die Zahlungsbedingungen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\n#### eine Zahlungsbedingung\n\n```ruby\npayment_term = client.income_payment_terms.find_by(id: 1)\nputs payment_term.headers\nputs payment_term.body\n```\n\n#### alle Zahlungsbedingungen\n\nSiehe [PaymentTerms](lib/papierkram_api/v1/endpoints/income/payment_terms.rb) für mögliche Parameter.\n\n```ruby\npayment_terms = client.income_payment_terms.all\nputs payment_terms.headers\nputs payment_terms.body\n```\n\n### Income::Proposition (Waren / Dienstleistungen)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/income/propositions` liefert Informationen über die Waren / Dienstleistungen. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Propositions](lib/papierkram_api/v1/endpoints/income/propositions.rb) für mögliche Parameter.\n\n#### alle Waren / Dienstleistungen\n\n```ruby\npropositions = client.income_propositions.all\nputs propositions.headers\nputs propositions.body\n```\n\n#### eine Ware / Dienstleistung\n\n```ruby\nproposition = client.income_propositions.find_by(id: 1)\nputs proposition.headers\nputs proposition.body\n```\n\n#### eine Ware / Dienstleistung erstellen\n\n```ruby\nproposition = client.income_propositions.create(\n  name: 'Software design',\n  article_no: '12345',\n  description: 'Here, we can describe what \"Software design\" actually entails.',\n  time_unit: 'hour',\n  proposition_type: 'service',\n  price: '150.0',\n  vat_rate: 0.19\n)\nputs proposition.headers\nputs proposition.body\n```\n\nSiehe [Propositions#create](lib/papierkram_api/v1/endpoints/income/propositions.rb) für mögliche Parameter.\n\n#### eine Ware / Dienstleistung aktualisieren\n\n```ruby\nclient.income_propositions.update_by(\n  id: 1,\n  name: 'Software design',\n  vat_rate: 0.19 # verpflichtend bei Änderung\n)\n```\n\nSiehe [Propositions#update_by](lib/papierkram_api/v1/endpoints/income/propositions.rb) für mögliche Parameter.\n\n#### eine Ware / Dienstleistung löschen\n\n```ruby\nclient.income_propositions.delete_by(id: 1)\n```\n\n#### eine Ware / Dienstleistung archivieren\n\n```ruby\nclient.income_propositions.archive_by(id: 1)\n```\n\n#### eine Ware / Dienstleistung unarchivieren\n\n```ruby\nclient.income_propositions.unarchive_by(id: 1)\n```\n\n### Info\n\nDer Endpunkt `lib/papierkram_api/v1/endpoints/info.rb` liefert Informationen über die API. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Info](lib/papierkram_api/v1/endpoints/info.rb).\n\n```ruby\ninfo = client.info.details\nputs info.headers\nputs info.body\n```\n\n### Project::Project (Projekt)\n\nDer Endpunkt `/papierkram_api/v1/endpoints/projects` liefert Informationen über die Projekte. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Projects](lib/papierkram_api/v1/endpoints/projects.rb) für mögliche Parameter.\n\n#### alle Projekte\n\n```ruby\nprojects = client.projects.all\nputs projects.headers\nputs projects.body\n```\n\n#### ein Projekt\n\n```ruby\nproject = client.projects.find_by(id: 1)\nputs project.headers\nputs project.body\n```\n\n#### erstelle ein Projekt\n\n```ruby\nproject = client.projects.create(name: 'Projekt 1')\nputs project.headers\nputs project.body\n```\n\nSiehe [Projects](lib/papierkram_api/v1/endpoints/projects.rb) für mögliche Parameter.\n\n#### aktualisiere ein Projekt\n\n```ruby\nproject = client.projects.update_by(\n  id: 1,\n  name: 'Projekt 2'\n)\nputs project.headers\nputs project.body\n```\n\nSiehe [Projects](lib/papierkram_api/v1/endpoints/projects.rb) für mögliche Parameter.\n\n#### lösche ein Projekt\n\n```ruby\nproject = client.projects.delete_by(id: 1)\nputs project.headers\nputs project.body\n```\n\n#### archiviere ein Projekt\n\n```ruby\nproject = client.projects.archive_by(id: 1)\nputs project.headers\nputs project.body\n```\n\n#### unarchiviere ein Projekt\n\n```ruby\nproject = client.projects.unarchive_by(id: 1)\nputs project.headers\nputs project.body\n```\n\n### Tracker::Task (Aufgabe)\n\nDer Endpunkt `/papierkram_api/v1/tracker/tasks` liefert Informationen über die Aufgaben. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\nSiehe [Tasks](lib/papierkram_api/v1/endpoints/tracker/tasks.rb) für mögliche Parameter.\n\n#### alle Aufgaben\n\n```ruby\ntasks = client.tracker_tasks.all\nputs tasks.headers\nputs tasks.body\n```\n\n#### eine Aufgabe\n\n```ruby\ntask = client.tracker_tasks.find_by(id: 1)\nputs task.headers\nputs task.body\n```\n\n#### erstelle eine Aufgabe\n\nSiehe [Tasks#create](lib/papierkram_api/v1/endpoints/tracker/tasks.rb) für mögliche Parameter.\n\n```ruby\ntask = client.tracker_tasks.create(name: 'Aufgabe 1')\nputs task.headers\nputs task.body\n```\n\n#### aktualisiere eine Aufgabe\n\nSiehe [Tasks#update_by](lib/papierkram_api/v1/endpoints/tracker/tasks.rb) für mögliche Parameter.\n\n```ruby\ntask = client.tracker_tasks.update_by(id: 1, name: 'Aufgabe 2' )\nputs task.headers\nputs task.body\n```\n\n#### lösche eine Aufgabe\n\n```ruby\ntask = client.tracker_tasks.delete_by(id: 1)\nputs task.headers\nputs task.body\n```\n\n#### archiviere eine Aufgabe\n\n```ruby\ntask = client.tracker_tasks.archive_by(id: 1)\nputs task.headers\nputs task.body\n```\n\n#### unarchiviere eine Aufgabe\n\n```ruby\ntask = client.tracker_tasks.unarchive_by(id: 1)\nputs task.headers\nputs task.body\n```\n\n### Tracker::TimeEntry (Zeiteintrag)\n\nDer Endpunkt `/papierkram_api/v1/tracker/time_entries` liefert Informationen über die Zeiteinträge. Die Informationen werden als `Faraday::Response` zurückgegeben.\n\n[TimeEntries](lib/papierkram_api/v1/endpoints/tracker/time_entries.rb)\n\n#### alle Zeiteinträge\n\nSiehe [TimeEntries](lib/papierkram_api/v1/endpoints/tracker/time_entries.rb) für mögliche Parameter.\n\n```ruby\ntime_entries = client.tracker_time_entries.all\nputs time_entries.headers\nputs time_entries.body\n```\n\n#### einen Zeiteintrag\n\n```ruby\ntime_entry = client.tracker_time_entries.find_by(id: 1)\nputs time_entry.headers\nputs time_entry.body\n```\n\n#### erstelle einen Zeiteintrag\n\nSiehe [TimeEntries](lib/papierkram_api/v1/endpoints/tracker/time_entries.rb) für mögliche Parameter.\n\n```ruby\ntime_entry = client.tracker_time_entries.create(\n  task_id: 1,\n  date: '2020-01-01',\n  duration: 60,\n  description: 'Test'\n)\nputs time_entry.headers\nputs time_entry.body\n```\n\n#### aktualisiere einen Zeiteintrag\n\nSiehe [TimeEntries](lib/papierkram_api/v1/endpoints/tracker/time_entries.rb) für mögliche Parameter.\n\n```ruby\ntime_entry = client.tracker_time_entries.update_by(\n  id: 1,\n comments: 'Test'\n)\nputs time_entry.headers\nputs time_entry.body\n```\n\n#### lösche einen Zeiteintrag\n\n```ruby\ntime_entry = client.tracker_time_entries.delete_by(id: 1)\nputs time_entry.headers\nputs time_entry.body\n```\n\n#### archiviere einen Zeiteintrag\n\n```ruby\ntime_entry = client.tracker_time_entries.archive_by(id: 1)\nputs time_entry.headers\nputs time_entry.body\n```\n\n#### unarchiviere einen Zeiteintrag\n\n```ruby\ntime_entry = client.tracker_time_entries.unarchive_by(id: 1)\nputs time_entry.headers\nputs time_entry.body\n```\n\n### Verbleibendes Quota\n\nJede API Anfrage \"kostet\" 1 Quota. Das Quota wird bei jedem Request aktualisiert. Um das verbleibende Quota zu erhalten, kann die Methode `remaining_quota` aufgerufen werden.\n\n[Base](lib/papierkram_api/v1/endpoints/base.rb)\n\nDu kannst dein Quota über die Papierkram Webseite einsehen. Die Anzahl der verbleibenden Anfragen wird dir dort angezeigt.\n\nOder nach jeder Anfrage per Client:\n\n```ruby\n# `client.info` ist nur eine Möglichkeit, es kann jeder andere Endpoint verwendet werden ✌️\nresponse = client.info.details\nquota = client.info.remaining_quota(response)\n```\n\n## Business Intelligence\n\n\u003e **DEPRECATED** Bitte verwende dieses Modul nicht mehr, es wird in Zukunft entfernt werden.\n\nIch 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.\n\nTODO ergänzen wie man `SmartQueries` erstellt und verwendet.  \nTODO ergänzen wie man `SmartQueries` funktioneren.  \nTODO ergänzen wie die Rückgabewerte von `SmartQueries` gestaltet werden sollten.\n\n### Business::Intelligence (BI) ExpenseByCategory (Ausgaben nach Kategorie)\n\n\u003e **DEPRECATED** Bitte verwende dieses Modul nicht mehr, es wird in Zukunft entfernt werden.\n\nDer Endpunkt `/papierkram_api/v1/business_intelligence/expense_by_categories` liefert Informationen über die Ausgaben nach Kategorie. Die Informationen werden als `Hash` zurückgegeben.\n\n#### alle Ausgaben eines Monats nach Kategorie\n\n```ruby\nclient = PapierkramApi::Client.new\nexpense_voucher_data_service = client.expense_vouchers.data_service(:for_month_in_year_service)\nexpense_vouchers_in_date_range = expense_voucher_data_service.for_month_in_year(year: 2020, month: 8)\n\nservice = client.business_intelligence.expenses_by_category\nresult = service.call(expense_vouchers: expense_vouchers_in_date_range)\nputs result\n```\n\n```ruby\n{\"Betriebsbedarf\"=\u003e\n  {\"amount\"=\u003e476.0,\n   \"amount_by_creditor\"=\u003e{nil=\u003e476.0},\n   \"line_items\"=\u003e\n    [{\"name\"=\u003e\"2020-01-03\",\n      \"amount\"=\u003e119.0,\n      \"category\"=\u003e\"Betriebsbedarf\",\n      \"vat_rate\"=\u003e\"19%\",\n      \"billing\"=\u003enil,\n      \"depreciation\"=\u003enil,\n      \"voucher_name\"=\u003e\"B-00214 - 2020-08-01\",\n      \"voucher_id\"=\u003e641,\n      \"creditor\"=\u003enil},\n     {\"name\"=\u003e\"2020-01-03\",\n      \"amount\"=\u003e119.0,\n      \"category\"=\u003e\"Betriebsbedarf\",\n      \"vat_rate\"=\u003e\"19%\",\n      \"billing\"=\u003enil,\n      \"depreciation\"=\u003enil,\n      \"voucher_name\"=\u003e\"B-00215 - 2020-08-02\",\n      \"voucher_id\"=\u003e644,\n      \"creditor\"=\u003enil},\n     {\"name\"=\u003e\"2020-01-03\",\n      \"amount\"=\u003e119.0,\n      \"category\"=\u003e\"Betriebsbedarf\",\n      \"vat_rate\"=\u003e\"19%\",\n      \"billing\"=\u003enil,\n      \"depreciation\"=\u003enil,\n      \"voucher_name\"=\u003e\"B-00216 - 2020-08-03\",\n      \"voucher_id\"=\u003e647,\n      \"creditor\"=\u003enil},\n     {\"name\"=\u003e\"2020-01-03\",\n      \"amount\"=\u003e119.0,\n      \"category\"=\u003e\"Betriebsbedarf\",\n      \"vat_rate\"=\u003e\"19%\",\n      \"billing\"=\u003enil,\n      \"depreciation\"=\u003enil,\n      \"voucher_name\"=\u003e\"B-00217 - 2020-08-04\",\n      \"voucher_id\"=\u003e650,\n      \"creditor\"=\u003enil}]}}\n```\n\n#### alle Ausgaben eines Monats nach Kategorie gefiltert nach Steuersatz\n\n```ruby\nclient = PapierkramApi::Client.new\nexpense_voucher_data_service = client.expense_vouchers.data_service(:for_month_in_year_service)\nexpense_vouchers_in_date_range = expense_voucher_data_service.for_month_in_year(year: 2020, month: 8)\n\nservice = client.business_intelligence.expenses_by_category\nresult = service.call(expense_vouchers: expense_vouchers_in_date_range) do |line_items|\n  line_items.select { |v| v['vat_rate'] == '19%' }\nend\nputs result\n```\n\n## Helpers\n\nEs gibt einige Helper, die dir das Leben leichter machen.\n\n### Generiere ein PDF aus Response\n\nMit dem Helper `PapierkramApi::V1::Helpers::PdfFromResponse` kannst du für unterstützte Endpunkte aus einer `Faraday::Response` ein PDF schreiben.\n\nUnterstützte Endpunkte sind beispielsweise: `Income::Estimate`, `Income::Invoice`, `Expense::Voucher`.\n\n[Api::V1::Helpers::PdfFromResponse](lib/papierkram_api/v1/helper/pdf_from_response.rb)\n\n```ruby\nresponse = client.income_invoices.find_by(id: 1, pdf: true)\npdf = PapierkramApi::V1::Helpers::PdfFromResponse.new(response).to_pdf(\"Rechnung Nummer XXX\")\nputs pdf\n```\n\n```ruby\n# value of `pdf`\n{\n  response: Faraday::Response,\n  path_to_pdf_file: 'path/to/temp/Rechnung Nummer XXX.pdf'\n}\n```\n\n## Development / Mitentwickeln\n\n🇬🇧/🇺🇸\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\nYou need to have at least the following environment variables set to run the tests:\n\n- `MT_COMPAT=true` or `export MT_COMPAT=true` (when in .envrc)\n\nPlease, see the [`.envrc.sample`](.envrc.sample) file for more (https://direnv.net/).\n\n🇩🇪\n\nNachdem du das Repository überprüft hast, führe `bin/setup` aus, um Abhängigkeiten zu installieren. Anschließend führe `rake test` aus, um die Tests durchzuführen. Du kannst auch `bin/console` ausführen, um eine interaktive Konsole zu starten und Experimente durchzuführen.\n\nUm dieses Gem auf deinem lokalen Rechner zu installieren, führe `bundle exec rake install` aus. Um eine neue Version zu veröffentlichen, aktualisiere die Versionsnummer in `version.rb` und führe dann `bundle exec rake release` aus. Dadurch wird ein Git-Tag für die Version erstellt, Git-Commits und das erstellte Tag werden gepusht, und die `.gem`-Datei wird nach [rubygems.org](https://rubygems.org) gepusht.\n\nUm die Tests auszuführen, muss die Umgebungsvariable `MT_COMPAT=true` gesetzt sein.\n\nBitte, schaue in die Datei [`.envrc.sample`](.envrc.sample) für mehr Details (https://direnv.net/).\n\n### Localhost 3000! 🤫\n\nEs gibt Menschen da draußen, die können gegen direkt gegen die Papierkram API entwickeln. 🤯  \nUnd wie das geht, verrate ich hier allen Lesern! 🤫\n\n`DEBUG_LOCALHOST=true bin/console`\n\nsiehe: [test/test_api_v1_client.rb](test/test_api_v1_client.rb)\n\nOR to make it stick:  \n- Set `export DEBUG_LOCALHOST=true` in your `.env` or `.envrc` file.  \n- Enjoy the magic: `bin/setup \u0026\u0026 bin/console` 🎉\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/simonneutert/papierkram_api_client.\n\nBitte achte darauf, dass du die Tests ausführst und die Tests dann auch grün sind 🤓\n\n🚨 **SEHR WICHTIG!** Dein API Key wird in den Tests verwendet werden. **Bitte achte darauf**, dass du den API Key nicht in deinen Commits hast! Wenn du per Environment Variable arbeitest, dann wird dein API Key **nicht von VCR aufgezeichnet**. Das bedeutet, dass du deine Tests nicht mit deinem API Key ausführen solltest. ⚠️\n\n🚨 **NOCH WICHTIGER!** deine Kundendaten, also Klarnamen, E-Mails und Telefonnummern haben hier nichts verloren! Bitte sorge dafür, dass du deine Tests mit einem Testaccount ausführst. 🙏 ODER editiere deine Kundendaten in den _VCR Cassettes_ nach dem Test. 🙏\n\nWenn du unsicher bist, sprich mich an oder erstelle ein Issue. Ich helfe dir gerne weiter. 🤗\n\n## Releasing\n\n1. checkout `main`\n2. close the changelog\n3. Set the correct/desired version number in `version.rb` and run `bundle install` just for sure\n4. commit changes if needed\n5. `bundle exec rake release`\n\nAfter a successful release, the gem is pushed to [rubygems.org](https://rubygems.org/gems/papierkram_api_client).\n\nHere are the steps you need to take after a successful release:\n\n1. edit `lib/papierkram_api_client/version.rb` and bump the version number to the next patch version\n2. run `bundle install`\n3. open the changelog again\n4. commit and push the changes\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonneutert%2Fpapierkram_api_client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonneutert%2Fpapierkram_api_client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonneutert%2Fpapierkram_api_client/lists"}