sevdesk 0.1.0__tar.gz

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 (143) hide show
  1. sevdesk-0.1.0/LICENSE +33 -0
  2. sevdesk-0.1.0/PKG-INFO +189 -0
  3. sevdesk-0.1.0/README.md +160 -0
  4. sevdesk-0.1.0/pyproject.toml +47 -0
  5. sevdesk-0.1.0/setup.cfg +4 -0
  6. sevdesk-0.1.0/sevdesk/__init__.py +3 -0
  7. sevdesk-0.1.0/sevdesk/base/basecontroller.py +102 -0
  8. sevdesk-0.1.0/sevdesk/client.py +81 -0
  9. sevdesk-0.1.0/sevdesk/controllers/accountingcontact_controller.py +33 -0
  10. sevdesk-0.1.0/sevdesk/controllers/basics_controller.py +9 -0
  11. sevdesk-0.1.0/sevdesk/controllers/checkaccount_controller.py +45 -0
  12. sevdesk-0.1.0/sevdesk/controllers/checkaccounttransaction_controller.py +38 -0
  13. sevdesk-0.1.0/sevdesk/controllers/communicationway_controller.py +38 -0
  14. sevdesk-0.1.0/sevdesk/controllers/contact_controller.py +53 -0
  15. sevdesk-0.1.0/sevdesk/controllers/contactaddress_controller.py +32 -0
  16. sevdesk-0.1.0/sevdesk/controllers/contactfield_controller.py +72 -0
  17. sevdesk-0.1.0/sevdesk/controllers/creditnote_controller.py +86 -0
  18. sevdesk-0.1.0/sevdesk/controllers/creditnotepos_controller.py +11 -0
  19. sevdesk-0.1.0/sevdesk/controllers/export_controller.py +77 -0
  20. sevdesk-0.1.0/sevdesk/controllers/invoice_controller.py +96 -0
  21. sevdesk-0.1.0/sevdesk/controllers/invoicepos_controller.py +11 -0
  22. sevdesk-0.1.0/sevdesk/controllers/layout_controller.py +32 -0
  23. sevdesk-0.1.0/sevdesk/controllers/order_controller.py +78 -0
  24. sevdesk-0.1.0/sevdesk/controllers/orderpos_controller.py +27 -0
  25. sevdesk-0.1.0/sevdesk/controllers/part_controller.py +32 -0
  26. sevdesk-0.1.0/sevdesk/controllers/report_controller.py +25 -0
  27. sevdesk-0.1.0/sevdesk/controllers/tag_controller.py +37 -0
  28. sevdesk-0.1.0/sevdesk/controllers/voucher_controller.py +80 -0
  29. sevdesk-0.1.0/sevdesk/controllers/voucherpos_controller.py +11 -0
  30. sevdesk-0.1.0/sevdesk/converters/accountdatev.py +7 -0
  31. sevdesk-0.1.0/sevdesk/converters/accountingtype.py +7 -0
  32. sevdesk-0.1.0/sevdesk/converters/addresscountry.py +7 -0
  33. sevdesk-0.1.0/sevdesk/converters/category.py +7 -0
  34. sevdesk-0.1.0/sevdesk/converters/checkaccount.py +7 -0
  35. sevdesk-0.1.0/sevdesk/converters/contact.py +7 -0
  36. sevdesk-0.1.0/sevdesk/converters/contactcustomfieldsetting.py +7 -0
  37. sevdesk-0.1.0/sevdesk/converters/contactperson.py +7 -0
  38. sevdesk-0.1.0/sevdesk/converters/costcentre.py +7 -0
  39. sevdesk-0.1.0/sevdesk/converters/country.py +7 -0
  40. sevdesk-0.1.0/sevdesk/converters/createuser.py +7 -0
  41. sevdesk-0.1.0/sevdesk/converters/creditnote.py +7 -0
  42. sevdesk-0.1.0/sevdesk/converters/discountdelete.py +8 -0
  43. sevdesk-0.1.0/sevdesk/converters/document.py +7 -0
  44. sevdesk-0.1.0/sevdesk/converters/error.py +8 -0
  45. sevdesk-0.1.0/sevdesk/converters/estimatedaccountingtype.py +7 -0
  46. sevdesk-0.1.0/sevdesk/converters/invoice.py +7 -0
  47. sevdesk-0.1.0/sevdesk/converters/key.py +7 -0
  48. sevdesk-0.1.0/sevdesk/converters/metadaten.py +9 -0
  49. sevdesk-0.1.0/sevdesk/converters/object.py +6 -0
  50. sevdesk-0.1.0/sevdesk/converters/object_.py +7 -0
  51. sevdesk-0.1.0/sevdesk/converters/order.py +7 -0
  52. sevdesk-0.1.0/sevdesk/converters/origin.py +7 -0
  53. sevdesk-0.1.0/sevdesk/converters/parent.py +7 -0
  54. sevdesk-0.1.0/sevdesk/converters/part.py +7 -0
  55. sevdesk-0.1.0/sevdesk/converters/paymentmethod.py +7 -0
  56. sevdesk-0.1.0/sevdesk/converters/sevclient.py +7 -0
  57. sevdesk-0.1.0/sevdesk/converters/sourcetransaction.py +7 -0
  58. sevdesk-0.1.0/sevdesk/converters/supplier.py +7 -0
  59. sevdesk-0.1.0/sevdesk/converters/tag.py +7 -0
  60. sevdesk-0.1.0/sevdesk/converters/targettransaction.py +7 -0
  61. sevdesk-0.1.0/sevdesk/converters/taxrule.py +7 -0
  62. sevdesk-0.1.0/sevdesk/converters/taxset.py +7 -0
  63. sevdesk-0.1.0/sevdesk/converters/unity.py +7 -0
  64. sevdesk-0.1.0/sevdesk/converters/voucher.py +7 -0
  65. sevdesk-0.1.0/sevdesk/models/accountingcontact.py +11 -0
  66. sevdesk-0.1.0/sevdesk/models/accountingcontactresponse.py +17 -0
  67. sevdesk-0.1.0/sevdesk/models/accountingcontactupdate.py +11 -0
  68. sevdesk-0.1.0/sevdesk/models/changelayout.py +8 -0
  69. sevdesk-0.1.0/sevdesk/models/changelayoutresponse.py +10 -0
  70. sevdesk-0.1.0/sevdesk/models/checkaccountresponse.py +28 -0
  71. sevdesk-0.1.0/sevdesk/models/checkaccounttransaction.py +27 -0
  72. sevdesk-0.1.0/sevdesk/models/checkaccounttransactionresponse.py +31 -0
  73. sevdesk-0.1.0/sevdesk/models/checkaccounttransactionupdate.py +19 -0
  74. sevdesk-0.1.0/sevdesk/models/checkaccountupdate.py +15 -0
  75. sevdesk-0.1.0/sevdesk/models/communicationway.py +20 -0
  76. sevdesk-0.1.0/sevdesk/models/communicationwayresponse.py +20 -0
  77. sevdesk-0.1.0/sevdesk/models/communicationwayupdate.py +14 -0
  78. sevdesk-0.1.0/sevdesk/models/contact.py +35 -0
  79. sevdesk-0.1.0/sevdesk/models/contactaddress.py +26 -0
  80. sevdesk-0.1.0/sevdesk/models/contactaddressresponse.py +26 -0
  81. sevdesk-0.1.0/sevdesk/models/contactaddressupdate.py +20 -0
  82. sevdesk-0.1.0/sevdesk/models/contactcustomfield.py +12 -0
  83. sevdesk-0.1.0/sevdesk/models/contactcustomfieldresponse.py +17 -0
  84. sevdesk-0.1.0/sevdesk/models/contactcustomfieldsetting.py +10 -0
  85. sevdesk-0.1.0/sevdesk/models/contactcustomfieldsettingresponse.py +16 -0
  86. sevdesk-0.1.0/sevdesk/models/contactcustomfieldsettingupdate.py +10 -0
  87. sevdesk-0.1.0/sevdesk/models/contactcustomfieldupdate.py +13 -0
  88. sevdesk-0.1.0/sevdesk/models/contactresponse.py +42 -0
  89. sevdesk-0.1.0/sevdesk/models/contactupdate.py +35 -0
  90. sevdesk-0.1.0/sevdesk/models/createclearingaccount.py +9 -0
  91. sevdesk-0.1.0/sevdesk/models/createclearingaccountresponse.py +19 -0
  92. sevdesk-0.1.0/sevdesk/models/createfileimportaccount.py +11 -0
  93. sevdesk-0.1.0/sevdesk/models/createfileimportaccountresponse.py +22 -0
  94. sevdesk-0.1.0/sevdesk/models/createinvoicefromorder.py +12 -0
  95. sevdesk-0.1.0/sevdesk/models/createpackinglistfromorder.py +8 -0
  96. sevdesk-0.1.0/sevdesk/models/creditnote.py +51 -0
  97. sevdesk-0.1.0/sevdesk/models/creditnote_mailresponse.py +18 -0
  98. sevdesk-0.1.0/sevdesk/models/creditnote_sendbywithrender.py +11 -0
  99. sevdesk-0.1.0/sevdesk/models/creditnotepos.py +32 -0
  100. sevdesk-0.1.0/sevdesk/models/creditnoteposresponse.py +31 -0
  101. sevdesk-0.1.0/sevdesk/models/creditnoteresponse.py +50 -0
  102. sevdesk-0.1.0/sevdesk/models/creditnoteupdate.py +50 -0
  103. sevdesk-0.1.0/sevdesk/models/discount.py +18 -0
  104. sevdesk-0.1.0/sevdesk/models/email.py +21 -0
  105. sevdesk-0.1.0/sevdesk/models/emailorder.py +21 -0
  106. sevdesk-0.1.0/sevdesk/models/export_job_download_info.py +10 -0
  107. sevdesk-0.1.0/sevdesk/models/export_progress_data.py +9 -0
  108. sevdesk-0.1.0/sevdesk/models/invoice.py +69 -0
  109. sevdesk-0.1.0/sevdesk/models/invoicepos.py +34 -0
  110. sevdesk-0.1.0/sevdesk/models/invoiceposresponse.py +33 -0
  111. sevdesk-0.1.0/sevdesk/models/invoiceresponse.py +76 -0
  112. sevdesk-0.1.0/sevdesk/models/iscountsresponse.py +17 -0
  113. sevdesk-0.1.0/sevdesk/models/order.py +44 -0
  114. sevdesk-0.1.0/sevdesk/models/orderpos.py +31 -0
  115. sevdesk-0.1.0/sevdesk/models/orderposresponse.py +31 -0
  116. sevdesk-0.1.0/sevdesk/models/orderposupdate.py +31 -0
  117. sevdesk-0.1.0/sevdesk/models/orderresponse.py +55 -0
  118. sevdesk-0.1.0/sevdesk/models/orderupdate.py +55 -0
  119. sevdesk-0.1.0/sevdesk/models/part.py +29 -0
  120. sevdesk-0.1.0/sevdesk/models/partupdate.py +29 -0
  121. sevdesk-0.1.0/sevdesk/models/receiptguidedto.py +13 -0
  122. sevdesk-0.1.0/sevdesk/models/savecreditnote.py +12 -0
  123. sevdesk-0.1.0/sevdesk/models/savecreditnoteresponse.py +9 -0
  124. sevdesk-0.1.0/sevdesk/models/saveinvoice.py +14 -0
  125. sevdesk-0.1.0/sevdesk/models/saveinvoiceresponse.py +10 -0
  126. sevdesk-0.1.0/sevdesk/models/saveorder.py +10 -0
  127. sevdesk-0.1.0/sevdesk/models/saveorderresponse.py +9 -0
  128. sevdesk-0.1.0/sevdesk/models/savevoucher.py +11 -0
  129. sevdesk-0.1.0/sevdesk/models/savevoucherresponse.py +10 -0
  130. sevdesk-0.1.0/sevdesk/models/tagcreateresponse.py +17 -0
  131. sevdesk-0.1.0/sevdesk/models/tagresponse.py +14 -0
  132. sevdesk-0.1.0/sevdesk/models/textparser_fetchdictionaryentriesbytype_response.py +9 -0
  133. sevdesk-0.1.0/sevdesk/models/validationerror.py +9 -0
  134. sevdesk-0.1.0/sevdesk/models/voucher.py +55 -0
  135. sevdesk-0.1.0/sevdesk/models/voucherpos.py +32 -0
  136. sevdesk-0.1.0/sevdesk/models/voucherposresponse.py +31 -0
  137. sevdesk-0.1.0/sevdesk/models/voucherresponse.py +55 -0
  138. sevdesk-0.1.0/sevdesk/models/voucherupdate.py +32 -0
  139. sevdesk-0.1.0/sevdesk.egg-info/PKG-INFO +189 -0
  140. sevdesk-0.1.0/sevdesk.egg-info/SOURCES.txt +141 -0
  141. sevdesk-0.1.0/sevdesk.egg-info/dependency_links.txt +1 -0
  142. sevdesk-0.1.0/sevdesk.egg-info/requires.txt +4 -0
  143. sevdesk-0.1.0/sevdesk.egg-info/top_level.txt +1 -0
sevdesk-0.1.0/LICENSE ADDED
@@ -0,0 +1,33 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Maximilian Clemens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ ÜBERSETZUNG, MAßGEBLICH BLEIBT ABER DIE ENGLISCHE ORIGINAL FASSUNG
26
+
27
+ Copyright (c) 2025 Maximilian Clemens
28
+
29
+ Jedem, der eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (die „Software“) erhält, wird hiermit kostenlos die Erlaubnis erteilt, ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software, und Personen, denen die Software zur Verfügung gestellt wird, dies unter den folgenden Bedingungen zu gestatten:
30
+
31
+ Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein.
32
+
33
+ DIE SOFTWARE WIRD OHNE MÄNGELGEWÄHR UND OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG, EINSCHLIEẞLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER, ZUR VERFÜGUNG GESTELLT. DIE AUTOREN ODER URHEBERRECHTSINHABER SIND IN KEINEM FALL HAFTBAR FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE VERPFLICHTUNGEN, OB IN EINER VERTRAGS- ODER HAFTUNGSKLAGE, EINER UNERLAUBTEN HANDLUNG ODER ANDERWEITIG, DIE SICH AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREN GESCHÄFTEN MIT DER SOFTWARE ERGEBEN.
sevdesk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: sevdesk
3
+ Version: 0.1.0
4
+ Summary: A Python client for the sevDesk API, automatically generated from the OpenAPI specification
5
+ Author: Claude, ChatGPT, Copilot
6
+ Author-email: Maximilian Clemens <maximilian.clemens@gamma.red>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/MaximilianClemens/python-sevdesk
9
+ Project-URL: Repository, https://github.com/MaximilianClemens/python-sevdesk
10
+ Project-URL: Issues, https://github.com/MaximilianClemens/python-sevdesk/issues
11
+ Keywords: sevdesk,api,client,accounting
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pydantic
25
+ Requires-Dist: requests
26
+ Requires-Dist: PyYAML
27
+ Requires-Dist: jinja2
28
+ Dynamic: license-file
29
+
30
+ # sevDesk API Client (Inoffiziell)
31
+
32
+ Ein Python-Client für die sevDesk API, automatisch generiert aus der OpenAPI-Spezifikation. Dies ist notwendig, da sich die sevdesk-Spezifikation mit dem Standard OpenApi-Generator nicht parsen lässt.
33
+
34
+ ## ⚠️ Wichtige Hinweise
35
+
36
+ - **Dies ist KEINE offizielle sevDesk Library**
37
+ - Ich arbeite nicht für sevDesk und bin nicht mit sevDesk verbunden
38
+ - **Nutzung auf eigene Gefahr**
39
+ - Keine Garantie für Funktionalität oder Vollständigkeit
40
+ - Bei Problemen mit Markenrechten oder dem Library-Namen kontaktieren Sie mich bitte
41
+ - Falls sich offizielle Vertreter von sevDesk am Namen der Library stören, bin ich bereit, diesen zu übertragen oder die Library unter einem anderen Namen zu veröffentlichen
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install sevdesk
47
+ ```
48
+
49
+ ## Anforderungen
50
+
51
+ - Python 3.8+
52
+ - pydantic
53
+ - requests
54
+ - pyyaml
55
+ - jinja2
56
+
57
+ ## Verwendung
58
+
59
+ ### Client initialisieren
60
+
61
+ ```python
62
+ from sevdesk import Client
63
+
64
+ # API Token von sevDesk Dashboard holen
65
+ client = Client('your-api-token-here')
66
+ ```
67
+
68
+ ### Kontakte abrufen
69
+
70
+ ```python
71
+ # Alle Kontakte abrufen
72
+ contacts = client.contact.getContacts()
73
+
74
+ for contact in contacts:
75
+ print(f"ID: {contact.id_}")
76
+ print(f"Name: {contact.name or f'{contact.surename} {contact.familyname}'}")
77
+ print(f"Kundennummer: {contact.customerNumber}")
78
+ print(f"Status: {contact.status}")
79
+ print("-" * 40)
80
+ ```
81
+
82
+ ### Neuen Kontakt erstellen
83
+
84
+ ```python
85
+ from sevdesk.models.contact import Contact
86
+ from sevdesk.converters.category import Category
87
+
88
+ # Organisation erstellen
89
+ company = Contact(
90
+ name="Acme Corporation GmbH",
91
+ category=Category(id_=3, objectName="Category")
92
+ )
93
+ new_company = client.contact.createContact(body=company)
94
+ print(f"Organisation erstellt mit ID: {new_company.id_}")
95
+
96
+ # Person erstellen
97
+ person = Contact(
98
+ surename="Max",
99
+ familyname="Mustermann",
100
+ gender="m",
101
+ category=Category(id_=3, objectName="Category")
102
+ )
103
+ new_person = client.contact.createContact(body=person)
104
+ print(f"Person erstellt mit ID: {new_person.id_}")
105
+ ```
106
+
107
+ ### Rechnungen abrufen
108
+
109
+ ```python
110
+ # Alle Rechnungen abrufen
111
+ invoices = client.invoice.getInvoices()
112
+
113
+ for invoice in invoices:
114
+ print(f"Rechnungsnummer: {invoice.invoiceNumber}")
115
+ print(f"Datum: {invoice.invoiceDate}")
116
+ print(f"Betrag: {invoice.sumGross} {invoice.currency}")
117
+ print(f"Status: {invoice.status}")
118
+ print("-" * 40)
119
+ ```
120
+
121
+ ### Angebote abrufen
122
+
123
+ ```python
124
+ # Alle Angebote abrufen
125
+ orders = client.order.getOrders()
126
+
127
+ for order in orders:
128
+ print(f"Angebotsnummer: {order.orderNumber}")
129
+ print(f"Datum: {order.orderDate}")
130
+ print(f"Betrag: {order.sumGross} {order.currency}")
131
+ print(f"Status: {order.status}")
132
+ print("-" * 40)
133
+ ```
134
+
135
+ ### Kontakt aktualisieren
136
+
137
+ ```python
138
+ from sevdesk.models.contactupdate import ContactUpdate
139
+
140
+ # Kontakt aktualisieren
141
+ update_data = ContactUpdate(
142
+ name="Neue Firma GmbH"
143
+ )
144
+ updated = client.contact.updateContact(contactId=123456, body=update_data)
145
+ print(f"Kontakt aktualisiert: {updated.name}")
146
+ ```
147
+
148
+ ### Kontakt löschen
149
+
150
+ ```python
151
+ # Kontakt löschen
152
+ client.contact.deleteContact(contactId=123456)
153
+ print("Kontakt gelöscht")
154
+ ```
155
+
156
+ ## Verfügbare Controller
157
+
158
+ Der Client lädt automatisch alle verfügbaren Controller aus der OpenAPI-Spezifikation:
159
+
160
+ - `client.contact` - Kontaktverwaltung
161
+ - `client.invoice` - Rechnungsverwaltung
162
+ - `client.order` - Angebotsverwaltung
163
+ - `client.voucher` - Belegverwaltung
164
+ - `client.part` - Artikelverwaltung
165
+ - ... und viele mehr
166
+
167
+ Alle Endpoints sind als Methoden verfügbar und vollständig typisiert für IDE-Unterstützung.
168
+
169
+ ## Code neu generieren
170
+
171
+ Falls sich die sevDesk API ändert:
172
+
173
+ ```bash
174
+ # Neue openapi.yaml herunterladen
175
+ # Dann Generator ausführen:
176
+ python -m generator
177
+ ```
178
+
179
+ Dies generiert automatisch:
180
+ - Models in `sevdeskapi/models/`
181
+ - Converter in `sevdeskapi/converters/`
182
+ - Controller in `sevdeskapi/controllers/`
183
+
184
+ Das wird zeitnah über Github Actions abgebildet!
185
+
186
+ ## Lizenz / Haftungsausschluss
187
+
188
+ MIT License - Siehe LICENSE Datei
189
+
@@ -0,0 +1,160 @@
1
+ # sevDesk API Client (Inoffiziell)
2
+
3
+ Ein Python-Client für die sevDesk API, automatisch generiert aus der OpenAPI-Spezifikation. Dies ist notwendig, da sich die sevdesk-Spezifikation mit dem Standard OpenApi-Generator nicht parsen lässt.
4
+
5
+ ## ⚠️ Wichtige Hinweise
6
+
7
+ - **Dies ist KEINE offizielle sevDesk Library**
8
+ - Ich arbeite nicht für sevDesk und bin nicht mit sevDesk verbunden
9
+ - **Nutzung auf eigene Gefahr**
10
+ - Keine Garantie für Funktionalität oder Vollständigkeit
11
+ - Bei Problemen mit Markenrechten oder dem Library-Namen kontaktieren Sie mich bitte
12
+ - Falls sich offizielle Vertreter von sevDesk am Namen der Library stören, bin ich bereit, diesen zu übertragen oder die Library unter einem anderen Namen zu veröffentlichen
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install sevdesk
18
+ ```
19
+
20
+ ## Anforderungen
21
+
22
+ - Python 3.8+
23
+ - pydantic
24
+ - requests
25
+ - pyyaml
26
+ - jinja2
27
+
28
+ ## Verwendung
29
+
30
+ ### Client initialisieren
31
+
32
+ ```python
33
+ from sevdesk import Client
34
+
35
+ # API Token von sevDesk Dashboard holen
36
+ client = Client('your-api-token-here')
37
+ ```
38
+
39
+ ### Kontakte abrufen
40
+
41
+ ```python
42
+ # Alle Kontakte abrufen
43
+ contacts = client.contact.getContacts()
44
+
45
+ for contact in contacts:
46
+ print(f"ID: {contact.id_}")
47
+ print(f"Name: {contact.name or f'{contact.surename} {contact.familyname}'}")
48
+ print(f"Kundennummer: {contact.customerNumber}")
49
+ print(f"Status: {contact.status}")
50
+ print("-" * 40)
51
+ ```
52
+
53
+ ### Neuen Kontakt erstellen
54
+
55
+ ```python
56
+ from sevdesk.models.contact import Contact
57
+ from sevdesk.converters.category import Category
58
+
59
+ # Organisation erstellen
60
+ company = Contact(
61
+ name="Acme Corporation GmbH",
62
+ category=Category(id_=3, objectName="Category")
63
+ )
64
+ new_company = client.contact.createContact(body=company)
65
+ print(f"Organisation erstellt mit ID: {new_company.id_}")
66
+
67
+ # Person erstellen
68
+ person = Contact(
69
+ surename="Max",
70
+ familyname="Mustermann",
71
+ gender="m",
72
+ category=Category(id_=3, objectName="Category")
73
+ )
74
+ new_person = client.contact.createContact(body=person)
75
+ print(f"Person erstellt mit ID: {new_person.id_}")
76
+ ```
77
+
78
+ ### Rechnungen abrufen
79
+
80
+ ```python
81
+ # Alle Rechnungen abrufen
82
+ invoices = client.invoice.getInvoices()
83
+
84
+ for invoice in invoices:
85
+ print(f"Rechnungsnummer: {invoice.invoiceNumber}")
86
+ print(f"Datum: {invoice.invoiceDate}")
87
+ print(f"Betrag: {invoice.sumGross} {invoice.currency}")
88
+ print(f"Status: {invoice.status}")
89
+ print("-" * 40)
90
+ ```
91
+
92
+ ### Angebote abrufen
93
+
94
+ ```python
95
+ # Alle Angebote abrufen
96
+ orders = client.order.getOrders()
97
+
98
+ for order in orders:
99
+ print(f"Angebotsnummer: {order.orderNumber}")
100
+ print(f"Datum: {order.orderDate}")
101
+ print(f"Betrag: {order.sumGross} {order.currency}")
102
+ print(f"Status: {order.status}")
103
+ print("-" * 40)
104
+ ```
105
+
106
+ ### Kontakt aktualisieren
107
+
108
+ ```python
109
+ from sevdesk.models.contactupdate import ContactUpdate
110
+
111
+ # Kontakt aktualisieren
112
+ update_data = ContactUpdate(
113
+ name="Neue Firma GmbH"
114
+ )
115
+ updated = client.contact.updateContact(contactId=123456, body=update_data)
116
+ print(f"Kontakt aktualisiert: {updated.name}")
117
+ ```
118
+
119
+ ### Kontakt löschen
120
+
121
+ ```python
122
+ # Kontakt löschen
123
+ client.contact.deleteContact(contactId=123456)
124
+ print("Kontakt gelöscht")
125
+ ```
126
+
127
+ ## Verfügbare Controller
128
+
129
+ Der Client lädt automatisch alle verfügbaren Controller aus der OpenAPI-Spezifikation:
130
+
131
+ - `client.contact` - Kontaktverwaltung
132
+ - `client.invoice` - Rechnungsverwaltung
133
+ - `client.order` - Angebotsverwaltung
134
+ - `client.voucher` - Belegverwaltung
135
+ - `client.part` - Artikelverwaltung
136
+ - ... und viele mehr
137
+
138
+ Alle Endpoints sind als Methoden verfügbar und vollständig typisiert für IDE-Unterstützung.
139
+
140
+ ## Code neu generieren
141
+
142
+ Falls sich die sevDesk API ändert:
143
+
144
+ ```bash
145
+ # Neue openapi.yaml herunterladen
146
+ # Dann Generator ausführen:
147
+ python -m generator
148
+ ```
149
+
150
+ Dies generiert automatisch:
151
+ - Models in `sevdeskapi/models/`
152
+ - Converter in `sevdeskapi/converters/`
153
+ - Controller in `sevdeskapi/controllers/`
154
+
155
+ Das wird zeitnah über Github Actions abgebildet!
156
+
157
+ ## Lizenz / Haftungsausschluss
158
+
159
+ MIT License - Siehe LICENSE Datei
160
+
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sevdesk"
7
+ dynamic = ["version"]
8
+ description = "A Python client for the sevDesk API, automatically generated from the OpenAPI specification"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ { name = "Maximilian Clemens", email = "maximilian.clemens@gamma.red" },
14
+ { name = "Claude" },
15
+ { name = "ChatGPT" },
16
+ { name = "Copilot" },
17
+ ]
18
+ keywords = ["sevdesk", "api", "client", "accounting"]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.8",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ ]
30
+ dependencies = [
31
+ "pydantic",
32
+ "requests",
33
+ "PyYAML",
34
+ "jinja2",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/MaximilianClemens/python-sevdesk"
39
+ Repository = "https://github.com/MaximilianClemens/python-sevdesk"
40
+ Issues = "https://github.com/MaximilianClemens/python-sevdesk/issues"
41
+
42
+ [tool.setuptools.dynamic]
43
+ version = {attr = "sevdesk.VERSION"}
44
+
45
+ [tool.setuptools.packages.find]
46
+ where = ["."]
47
+ include = ["sevdesk*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ VERSION = "0.1.0"
2
+
3
+ from sevdesk.client import Client
@@ -0,0 +1,102 @@
1
+ import inspect
2
+ from typing import get_type_hints, get_origin, get_args
3
+
4
+ class BaseController:
5
+ def __init__(self, client):
6
+ self.client = client
7
+
8
+ @staticmethod
9
+ def parse_response(response, return_type):
10
+ """Wandelt die Response in das entsprechende Model um"""
11
+ if return_type is None:
12
+ return response
13
+
14
+ # Hole den ursprünglichen Typ (ohne list[] wrapper)
15
+ origin = get_origin(return_type)
16
+
17
+ # Wenn es eine Liste ist
18
+ if origin is list:
19
+ args = get_args(return_type)
20
+ if args:
21
+ model_class = args[0]
22
+ # Response sollte eine Liste von Dicts sein
23
+ if isinstance(response, dict) and 'objects' in response:
24
+ # sevDesk API struktur: {"objects": [...]}
25
+ return [model_class(**item) if isinstance(item, dict) else item
26
+ for item in response['objects']]
27
+ elif isinstance(response, list):
28
+ return [model_class(**item) if isinstance(item, dict) else item
29
+ for item in response]
30
+
31
+ # Einzelnes Model
32
+ elif hasattr(return_type, '__bases__'): # Check if it's a class
33
+ if isinstance(response, dict):
34
+ # sevDesk API struktur kann auch {"objects": {...}} sein
35
+ if 'objects' in response and isinstance(response['objects'], dict):
36
+ return return_type(**response['objects'])
37
+ else:
38
+ return return_type(**response)
39
+
40
+ return response
41
+
42
+ @staticmethod
43
+ def request(method, path):
44
+ def decorator(func):
45
+ def wrapper(self, *args, **kwargs):
46
+ # Args in kwargs umwandeln
47
+ sig = inspect.signature(func)
48
+ bound_args = sig.bind(self, *args, **kwargs)
49
+ bound_args.apply_defaults()
50
+
51
+ # Entferne 'self' aus den arguments
52
+ all_kwargs = dict(bound_args.arguments)
53
+ all_kwargs.pop('self', None)
54
+
55
+ gen = func(self, **all_kwargs)
56
+
57
+ try:
58
+ # Pre-request: bis zum yield ausführen
59
+ next(gen)
60
+ # veränderte parameter übernehmen
61
+ for arg in all_kwargs.copy():
62
+ # gi_frame HACK
63
+ if gen.gi_frame:
64
+ all_kwargs[arg] = gen.gi_frame.f_locals[arg]
65
+
66
+ response = self.client.request(method, path, all_kwargs)
67
+
68
+ # Return Type aus der Funktion auslesen
69
+ try:
70
+ type_hints = get_type_hints(func)
71
+ return_type = type_hints.get('return', None)
72
+ except Exception:
73
+ return_type = None
74
+
75
+ # Response in Model umwandeln
76
+ parsed_response = BaseController.parse_response(response, return_type)
77
+
78
+ # Gebe das Ergebnis direkt zurück
79
+ return parsed_response
80
+
81
+ except StopIteration:
82
+ return None
83
+
84
+ wrapper.__name__ = func.__name__
85
+ return wrapper
86
+ return decorator
87
+
88
+ @staticmethod
89
+ def get(path):
90
+ return BaseController.request('get', path)
91
+
92
+ @staticmethod
93
+ def post(path):
94
+ return BaseController.request('post', path)
95
+
96
+ @staticmethod
97
+ def put(path):
98
+ return BaseController.request('put', path)
99
+
100
+ @staticmethod
101
+ def delete(path):
102
+ return BaseController.request('delete', path)
@@ -0,0 +1,81 @@
1
+ import requests
2
+ import re
3
+ import importlib
4
+ from pathlib import Path
5
+
6
+ class Client:
7
+
8
+ def __init__(self, api_token, api_base='https://my.sevdesk.de/api/v1', session=None):
9
+ self.api_token = api_token
10
+ self.api_base = api_base
11
+ self.session = session
12
+ if not self.session:
13
+ self.session = requests.Session()
14
+
15
+ # Automatisch alle Controller laden
16
+ self._load_controllers()
17
+
18
+ def _load_controllers(self):
19
+ """Lädt automatisch alle Controller aus dem controllers Verzeichnis"""
20
+ controllers_dir = Path(__file__).parent / "controllers"
21
+
22
+ if not controllers_dir.exists():
23
+ return
24
+
25
+ for controller_file in controllers_dir.glob("*_controller.py"):
26
+ # z.B. "contact_controller.py" -> "contact"
27
+ controller_name = controller_file.stem.replace("_controller", "")
28
+
29
+ try:
30
+ # Dynamisch importieren
31
+ module = importlib.import_module(f"sevdesk.controllers.{controller_file.stem}")
32
+
33
+ # Finde die Controller-Klasse im Modul (endet mit "Controller")
34
+ controller_class = None
35
+ for attr_name in dir(module):
36
+ attr = getattr(module, attr_name)
37
+ if (isinstance(attr, type) and
38
+ attr_name.endswith("Controller") and
39
+ attr_name != "BaseController"):
40
+ controller_class = attr
41
+ break
42
+
43
+ if controller_class:
44
+ # Als Attribut setzen: self.contact = ContactController(self)
45
+ setattr(self, controller_name, controller_class(self))
46
+ else:
47
+ print(f"Warning: No controller class found in {controller_file.stem}")
48
+
49
+ except (ImportError, AttributeError) as e:
50
+ print(f"Warning: Could not load controller {controller_name}: {e}")
51
+
52
+ def request(self, method, path, params):
53
+ url_params = re.findall(r"{(\w+)}", path)
54
+ request_path = path.format(**params)
55
+
56
+ request_params = {
57
+ k: v for k, v in params.items()
58
+ if k not in url_params and
59
+ k != 'body' and
60
+ v} # v not None
61
+ request_url = f'{self.api_base}{request_path}'
62
+ request_body = params.get('body', None)
63
+ if request_body:
64
+ request_body = request_body.model_dump(by_alias=True, exclude_none=True)
65
+
66
+ # print('request_params', request_params)
67
+ # print('request_url', request_url)
68
+ # print('request_body', request_body)
69
+
70
+ response = self.session.request(
71
+ method=method,
72
+ url=request_url,
73
+ params=request_params,
74
+ json=request_body,
75
+ headers={
76
+ 'Authorization': self.api_token
77
+ }
78
+ )
79
+ # print(response.status_code)
80
+ # print(response.text)
81
+ return response.json()
@@ -0,0 +1,33 @@
1
+ from sevdesk.base.basecontroller import BaseController
2
+ from typing import Optional
3
+ from sevdesk.models.accountingcontact import AccountingContact
4
+ from sevdesk.models.accountingcontactresponse import AccountingContactResponse
5
+ from sevdesk.models.accountingcontactupdate import AccountingContactUpdate
6
+
7
+ class AccountingContactController(BaseController):
8
+
9
+ @BaseController.get("/AccountingContact")
10
+ def getAccountingContact(self, contact_id: Optional[str] = None, contact_objectName: Optional[str] = None) -> list[AccountingContactResponse]:
11
+ """Retrieve accounting contact"""
12
+ return (yield)
13
+
14
+ @BaseController.post("/AccountingContact")
15
+ def createAccountingContact(self, body: AccountingContact) -> AccountingContactResponse:
16
+ """Create a new accounting contact"""
17
+ return (yield)
18
+
19
+ @BaseController.get("/AccountingContact/{accountingContactId}")
20
+ def getAccountingContactById(self, accountingContactId: int) -> list[AccountingContactResponse]:
21
+ """Find accounting contact by ID"""
22
+ return (yield)
23
+
24
+ @BaseController.put("/AccountingContact/{accountingContactId}")
25
+ def updateAccountingContact(self, accountingContactId: int, body: AccountingContactUpdate) -> AccountingContactResponse:
26
+ """Update an existing accounting contact"""
27
+ return (yield)
28
+
29
+ @BaseController.delete("/AccountingContact/{accountingContactId}")
30
+ def deleteAccountingContact(self, accountingContactId: int):
31
+ """Deletes an accounting contact"""
32
+ return (yield)
33
+
@@ -0,0 +1,9 @@
1
+ from sevdesk.base.basecontroller import BaseController
2
+
3
+ class BasicsController(BaseController):
4
+
5
+ @BaseController.get("/Tools/bookkeepingSystemVersion")
6
+ def bookkeepingSystemVersion(self):
7
+ """Retrieve bookkeeping system version"""
8
+ return (yield)
9
+