python-easyverein 0.1.2__tar.gz → 0.2.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 (34) hide show
  1. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/PKG-INFO +3 -2
  2. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/README.md +2 -1
  3. python_easyverein-0.2.0/easyverein/__init__.py +13 -0
  4. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/client.py +9 -3
  5. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/types.py +10 -0
  6. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/contact_details.py +30 -2
  7. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/custom_field.py +20 -1
  8. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/invoice.py +57 -1
  9. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/invoice_item.py +24 -2
  10. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/member.py +83 -3
  11. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/member_custom_field.py +22 -1
  12. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/contact_details.py +4 -1
  13. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/custom_field.py +7 -2
  14. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/invoice.py +3 -2
  15. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/invoice_item.py +9 -2
  16. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/member.py +2 -2
  17. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/member_custom_field.py +7 -1
  18. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/mixins/crud.py +29 -8
  19. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/mixins/recycle_bin.py +1 -1
  20. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/pyproject.toml +1 -1
  21. python_easyverein-0.1.2/easyverein/__init__.py +0 -8
  22. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/LICENSE +0 -0
  23. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/api.py +0 -0
  24. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/__init__.py +0 -0
  25. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/exceptions.py +0 -0
  26. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/protocol.py +0 -0
  27. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/core/validators.py +0 -0
  28. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/__init__.py +0 -0
  29. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/base.py +0 -0
  30. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/mixins/__init__.py +0 -0
  31. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/mixins/empty_strings_mixin.py +0 -0
  32. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/models/mixins/required_attributes.py +0 -0
  33. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/__init__.py +0 -0
  34. {python_easyverein-0.1.2 → python_easyverein-0.2.0}/easyverein/modules/mixins/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-easyverein
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Python library to interact with the EasyVerein API
5
5
  Author: Daniel Herrmann
6
6
  Author-email: daniel.herrmann1@gmail.com
@@ -18,7 +18,8 @@ Description-Content-Type: text/markdown
18
18
  ![GitHub issues](https://img.shields.io/github/issues/waza-ari/python-easyverein)
19
19
  ![GitHub release (latest by date)](https://img.shields.io/github/v/release/waza-ari/python-easyverein)
20
20
  ![GitHub top language](https://img.shields.io/github/languages/top/waza-ari/python-easyverein)
21
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/waza-ari/python-easyverein/development.svg)](https://results.pre-commit.ci/latest/github/waza-ari/python-easyverein/development)
21
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/waza-ari/python-easyverein/main.svg)](https://results.pre-commit.ci/latest/github/waza-ari/python-easyverein/main)
22
+
22
23
 
23
24
 
24
25
  # Python EasyVerein
@@ -3,7 +3,8 @@
3
3
  ![GitHub issues](https://img.shields.io/github/issues/waza-ari/python-easyverein)
4
4
  ![GitHub release (latest by date)](https://img.shields.io/github/v/release/waza-ari/python-easyverein)
5
5
  ![GitHub top language](https://img.shields.io/github/languages/top/waza-ari/python-easyverein)
6
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/waza-ari/python-easyverein/development.svg)](https://results.pre-commit.ci/latest/github/waza-ari/python-easyverein/development)
6
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/waza-ari/python-easyverein/main.svg)](https://results.pre-commit.ci/latest/github/waza-ari/python-easyverein/main)
7
+
7
8
 
8
9
 
9
10
  # Python EasyVerein
@@ -0,0 +1,13 @@
1
+ """
2
+ Middleware for FastAPI that supports authenticating users against Keycloak
3
+ """
4
+
5
+ __version__ = "0.2.0"
6
+
7
+ # Export EasyVerein API directly
8
+ from .api import EasyvereinAPI # noqa: F401
9
+ from .core.exceptions import ( # noqa: F401
10
+ EasyvereinAPIException,
11
+ EasyvereinAPINotFoundException,
12
+ EasyvereinAPITooManyRetriesException,
13
+ )
@@ -210,14 +210,20 @@ class EasyvereinClient:
210
210
  status_code,
211
211
  )
212
212
 
213
- def fetch(self, url, model: type[T] = None) -> list[T]:
213
+ def fetch(self, url, model: type[T] = None) -> tuple[list[T], int]:
214
214
  """
215
215
  Helper method that fetches a result from an API call
216
216
 
217
217
  Only supports GET endpoints
218
218
  """
219
219
  res = self._do_request("get", url)
220
- return self._handle_response(res, model, 200)
220
+ data = self._handle_response(res, model, 200)
221
+ try:
222
+ total_count = res[1]["count"]
223
+ except KeyError:
224
+ total_count = 0
225
+
226
+ return data, total_count
221
227
 
222
228
  def fetch_one(self, url, model: type[T] = None) -> T | None:
223
229
  """
@@ -225,7 +231,7 @@ class EasyvereinClient:
225
231
 
226
232
  Only supports GET endpoints
227
233
  """
228
- reply = self.fetch(url, model)
234
+ reply, _ = self.fetch(url, model)
229
235
  if isinstance(reply, list):
230
236
  if len(reply) == 0:
231
237
  return None
@@ -30,3 +30,13 @@ HexColor = Annotated[
30
30
  str | None,
31
31
  Field(min_length=7, max_length=7),
32
32
  ]
33
+
34
+ FilterIntList = Annotated[
35
+ list[int],
36
+ PlainSerializer(lambda x: ",".join([str(i) for i in x]), return_type=str),
37
+ ]
38
+
39
+ FilterStrList = Annotated[
40
+ list[str],
41
+ PlainSerializer(lambda x: ",".join(x), return_type=str),
42
+ ]
@@ -5,9 +5,9 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Any, Literal
7
7
 
8
- from pydantic import EmailStr, Field
8
+ from pydantic import BaseModel, EmailStr, Field
9
9
 
10
- from ..core.types import Date, DateTime
10
+ from ..core.types import Date, DateTime, FilterIntList
11
11
  from .base import EasyVereinBase
12
12
  from .mixins.required_attributes import required_mixin
13
13
 
@@ -135,3 +135,31 @@ class ContactDetailsCreate(ContactDetailsUpdate, required_mixin(["isCompany"])):
135
135
  """
136
136
  Pydantic model for creating new contact details
137
137
  """
138
+
139
+
140
+ class ContactDetailsFilter(BaseModel):
141
+ """
142
+ Pydantic model used to filter contact details
143
+ """
144
+
145
+ id__in: FilterIntList | None = None
146
+ country: str | None = None
147
+ isCompany: bool = Field(default=None, serialization_alias="_isCompany")
148
+ preferredCommunicationWay: str | None = None
149
+ contactDetailsGroups: str | None = None
150
+ contactDetailsGroups__not: str | None = None
151
+ dateOfBirthUnset: bool | None = None
152
+ showBirthdaysBetween: str | None = None
153
+ deleted: bool | None = None
154
+ firstName: str | None = None
155
+ familyName: str | None = None
156
+ companyName: str | None = None
157
+ isReferencedByOrgUser: bool | None = None
158
+ lat: str | None = None
159
+ lng: str | None = None
160
+ hasCopyInOrg: str | None = None
161
+ hasCopyInOrg__not: str | None = None
162
+ isCopy: bool | None = None
163
+ hasCopy: bool | None = None
164
+ ordering: str | None = None
165
+ search: str | None = None
@@ -5,10 +5,11 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Literal
7
7
 
8
- from pydantic import Field
8
+ from pydantic import BaseModel, Field
9
9
 
10
10
  from ..core.types import (
11
11
  EasyVereinReference,
12
+ FilterIntList,
12
13
  HexColor,
13
14
  OptionsField,
14
15
  PositiveIntWithZero,
@@ -91,3 +92,21 @@ class CustomFieldUpdate(CustomField):
91
92
  """
92
93
 
93
94
  pass
95
+
96
+
97
+ class CustomFieldFilter(BaseModel):
98
+ """
99
+ Pydantic model used to filter custom fields
100
+ """
101
+
102
+ id__in: FilterIntList | None = None
103
+ name: str | None = None
104
+ color: str | None = None
105
+ kind: str | None = None
106
+ member_edit: bool | None = None
107
+ member_show: bool | None = None
108
+ deletedBy__isnull: bool = Field(
109
+ default=None, serialization_alias="_deletedBy__isnull"
110
+ )
111
+ deleted: bool | None = None
112
+ ordering: str | None = None
@@ -5,7 +5,15 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Literal
7
7
 
8
- from ..core.types import Date, EasyVereinReference, PositiveIntWithZero
8
+ from pydantic import BaseModel
9
+
10
+ from ..core.types import (
11
+ Date,
12
+ EasyVereinReference,
13
+ FilterIntList,
14
+ FilterStrList,
15
+ PositiveIntWithZero,
16
+ )
9
17
  from .base import EasyVereinBase
10
18
  from .mixins.required_attributes import required_mixin
11
19
 
@@ -73,5 +81,53 @@ class InvoiceUpdate(Invoice):
73
81
  """
74
82
 
75
83
 
84
+ class InvoiceFilter(BaseModel):
85
+ """
86
+ Pydantic model used to filter invoices
87
+ """
88
+
89
+ id__in: FilterIntList | None = None
90
+ relatedAddress: int | None = None
91
+ relatedAddress__isnull: bool = None
92
+ relatedBookings: FilterIntList | None = None
93
+ relatedBookings__isnull: bool = None
94
+ relatedBookings__ne: FilterIntList | None = None
95
+ payedFromUser: int | None = None
96
+ payedFromUser__isnull: bool = None
97
+ approvedFromAdmin: int | None = None
98
+ approvedFromAdmin__isnull: bool = None
99
+ canceledInvoice__isnull: bool = None
100
+ date: Date | None = None
101
+ date__gt: Date | None = None
102
+ date__lt: Date | None = None
103
+ dateItHappened: Date | None = None
104
+ dateItHappened__gt: Date | None = None
105
+ dateItHappened__lt: Date | None = None
106
+ invNumber__in: FilterStrList | None = None
107
+ receiver: str | None = None
108
+ totalPrice: float | None = None
109
+ totalPrice__gte: float | None = None
110
+ totalPrice__lte: float | None = None
111
+ kind: str | None = None
112
+ kind__in: FilterStrList | None = None
113
+ refNumber: str | None = None
114
+ paymentDifference: float | None = None
115
+ paymentDifference__gte: float | None = None
116
+ paymentDifference__lte: float | None = None
117
+ paymentDifference__ne: float | None = None
118
+ isRequest: bool | None = None
119
+ accnumber: int | None = None
120
+ accnumber__ne: int | None = None
121
+ isDraft: bool | None = None
122
+ isTemplate: bool | None = None
123
+ actualCallStateName: str | None = None
124
+ actualCallStateName__ne: str | None = None
125
+ deleted: bool | None = None
126
+ customfilter: int | None = None
127
+ usesessionfilter: bool | None = None
128
+ ordering: str | None = None
129
+ search: str | None = None
130
+
131
+
76
132
  from .invoice_item import InvoiceItem # noqa: E402
77
133
  from .member import Member # noqa: E402
@@ -5,9 +5,9 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Annotated
7
7
 
8
- from pydantic import PositiveInt, StringConstraints
8
+ from pydantic import BaseModel, PositiveInt, StringConstraints
9
9
 
10
- from ..core.types import EasyVereinReference
10
+ from ..core.types import EasyVereinReference, FilterIntList
11
11
  from .base import EasyVereinBase
12
12
  from .mixins.required_attributes import required_mixin
13
13
 
@@ -53,4 +53,26 @@ class InvoiceItemUpdate(InvoiceItem):
53
53
  """
54
54
 
55
55
 
56
+ class InvoiceItemFilter(BaseModel):
57
+ """
58
+ Pydantic model used to filter invoice items
59
+ """
60
+
61
+ id__in: FilterIntList | None = None
62
+ title: str | None = None
63
+ taxName: str | None = None
64
+ quantity__gte: int | None = None
65
+ quantity__lte: int | None = None
66
+ description: str | None = None
67
+ billingAccount__isnull: bool | None = None
68
+ relatedInvoice: int | None = None
69
+ relatedInvoice__not: int | None = None
70
+ relatedInvoice__isDraft: bool | None = None
71
+ relatedInvoice__isTemplate: bool | None = None
72
+ billingAccount: str | None = None
73
+ billingAccount__not: str | None = None
74
+ ordering: str | None = None
75
+ search: str | None = None
76
+
77
+
56
78
  from .invoice import Invoice # noqa: E402
@@ -5,9 +5,15 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Literal
7
7
 
8
- from pydantic import Field, PositiveInt
9
-
10
- from ..core.types import AnyHttpURL, DateTime, EasyVereinReference
8
+ from pydantic import BaseModel, Field, PositiveInt
9
+
10
+ from ..core.types import (
11
+ AnyHttpURL,
12
+ DateTime,
13
+ EasyVereinReference,
14
+ FilterIntList,
15
+ FilterStrList,
16
+ )
11
17
  from .base import EasyVereinBase
12
18
  from .mixins.required_attributes import required_mixin
13
19
 
@@ -120,5 +126,79 @@ class MemberCreate(MemberUpdate, required_mixin(["contactDetails"])):
120
126
  emailOrUserName: str
121
127
 
122
128
 
129
+ class MemberFilter(BaseModel):
130
+ """
131
+ Pydantic model used to filter members
132
+ """
133
+
134
+ id__in: FilterIntList | None = None
135
+ paymentAmount__gt: float | None = None
136
+ paymentAmount__lt: float | None = None
137
+ paymentAmount: float | None = None
138
+ paymentAmount__ne: float | None = None
139
+ email: str | None = None
140
+ email__ne: str | None = None
141
+ contactDetails: str | None = None
142
+ contactDetails__preferredCommunicationWay: int | None = None
143
+ contactDetails__preferredCommunicationWay__ne: int | None = None
144
+ contactDetails__country: str | None = None
145
+ membershipNumber: str | None = None
146
+ membershipNumber__in: FilterStrList | None = None
147
+ deletedBy: int = Field(default=None, serialization_alias="_deletedBy")
148
+ deletedBy__ne: int = Field(default=None, serialization_alias="_deletedBy__ne")
149
+ deletedBy__isnull: bool = Field(
150
+ default=None, serialization_alias="_deletedBy__isnull"
151
+ )
152
+ joinDate: DateTime | None = None
153
+ joinDate__gte: DateTime | None = None
154
+ joinDate__lte: DateTime | None = None
155
+ joinDate__isnull: DateTime | None = None
156
+ resignationDate: DateTime | None = None
157
+ resignationDate__gte: DateTime | None = None
158
+ resignationDate__lte: DateTime | None = None
159
+ resignationDate__isnull: DateTime | None = None
160
+ isApplication: bool = Field(default=None, serialization_alias="_isApplication")
161
+ applicationDate: DateTime = Field(
162
+ default=None, serialization_alias="_applicationDate"
163
+ )
164
+ applicationDate__gte: DateTime = Field(
165
+ default=None, serialization_alias="_applicationDate__gte"
166
+ )
167
+ applicationDate__lte: DateTime = Field(
168
+ default=None, serialization_alias="_applicationDate__lte"
169
+ )
170
+ applicationDate__isnull: DateTime = Field(
171
+ default=None, serialization_alias="_applicationDate__isnull"
172
+ )
173
+ applicationWasAcceptedAt: DateTime = Field(
174
+ default=None, serialization_alias="_applicationWasAcceptedAt"
175
+ )
176
+ applicationWasAcceptedAt__gte: DateTime = Field(
177
+ default=None, serialization_alias="_applicationWasAcceptedAt__gte"
178
+ )
179
+ applicationWasAcceptedAt__lte: DateTime = Field(
180
+ default=None, serialization_alias="_applicationWasAcceptedAt__lte"
181
+ )
182
+ applicationWasAcceptedAt__isnull: bool = Field(
183
+ default=None, serialization_alias="_applicationWasAcceptedAt__isnull"
184
+ )
185
+ isChairman: bool = Field(default=None, serialization_alias="_isChairman")
186
+ memberGroups: str | None = None
187
+ memberGroups__not: str | None = None
188
+ deleted: bool | None = None
189
+ custom_field_name: str | None = None
190
+ custom_field_value: str | None = None
191
+ custom_field_value__in: FilterStrList | None = None
192
+ custom_field_value__not_in: FilterStrList | None = None
193
+ ordering: str | None = None
194
+ showOnlyUpcomingBirthdays: bool | None = None
195
+ showOnlyUpcomingAnniversaries: bool | None = None
196
+ hasCopyInOrg: str | None = None
197
+ hasCopyInOrg__not: str | None = None
198
+ isCopy: bool | None = None
199
+ hasCopy: bool | None = None
200
+ search: str | None = None
201
+
202
+
123
203
  from .contact_details import ContactDetails # noqa: E402
124
204
  from .member_custom_field import MemberCustomField # noqa: E402
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from ..core.types import EasyVereinReference
3
+ from pydantic import BaseModel
4
+
5
+ from ..core.types import EasyVereinReference, FilterIntList
4
6
  from .base import EasyVereinBase
5
7
  from .mixins.required_attributes import required_mixin
6
8
 
@@ -47,5 +49,24 @@ class MemberCustomFieldUpdate(MemberCustomField):
47
49
  pass
48
50
 
49
51
 
52
+ class MemberCustomFieldFilter(BaseModel):
53
+ """
54
+ Pydantic model used to filter members custom fields
55
+ """
56
+
57
+ id__in: FilterIntList | None = None
58
+ paymentActive: bool | None = None
59
+ start__gte: str | None = None
60
+ start__lte: str | None = None
61
+ start: str | None = None
62
+ end__gte: str | None = None
63
+ end__lte: str | None = None
64
+ end: str | None = None
65
+ deleted: bool | None = None
66
+ memberGroup: str | None = None
67
+ memberGroup__not: str | None = None
68
+ ordering: str | None = None
69
+
70
+
50
71
  from .custom_field import CustomField # noqa: E402
51
72
  from .member import Member # noqa: E402
@@ -5,12 +5,15 @@ import logging
5
5
 
6
6
  from ..core.client import EasyvereinClient
7
7
  from ..models import ContactDetails, ContactDetailsCreate, ContactDetailsUpdate
8
+ from ..models.contact_details import ContactDetailsFilter
8
9
  from .mixins.crud import CRUDMixin
9
10
  from .mixins.recycle_bin import RecycleBinMixin
10
11
 
11
12
 
12
13
  class ContactDetailsMixin(
13
- CRUDMixin[ContactDetails, ContactDetailsCreate, ContactDetailsUpdate],
14
+ CRUDMixin[
15
+ ContactDetails, ContactDetailsCreate, ContactDetailsUpdate, ContactDetailsFilter
16
+ ],
14
17
  RecycleBinMixin[ContactDetails],
15
18
  ):
16
19
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
@@ -4,13 +4,18 @@ All methods related to custom fields
4
4
  import logging
5
5
 
6
6
  from ..core.client import EasyvereinClient
7
- from ..models.custom_field import CustomField, CustomFieldCreate, CustomFieldUpdate
7
+ from ..models.custom_field import (
8
+ CustomField,
9
+ CustomFieldCreate,
10
+ CustomFieldFilter,
11
+ CustomFieldUpdate,
12
+ )
8
13
  from .mixins.crud import CRUDMixin
9
14
  from .mixins.recycle_bin import RecycleBinMixin
10
15
 
11
16
 
12
17
  class CustomFieldMixin(
13
- CRUDMixin[CustomField, CustomFieldCreate, CustomFieldUpdate],
18
+ CRUDMixin[CustomField, CustomFieldCreate, CustomFieldUpdate, CustomFieldFilter],
14
19
  RecycleBinMixin[CustomField],
15
20
  ):
16
21
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
@@ -4,14 +4,15 @@ from typing import List
4
4
 
5
5
  from ..core.client import EasyvereinClient
6
6
  from ..core.exceptions import EasyvereinAPIException
7
- from ..models.invoice import Invoice, InvoiceCreate, InvoiceUpdate
7
+ from ..models.invoice import Invoice, InvoiceCreate, InvoiceFilter, InvoiceUpdate
8
8
  from ..models.invoice_item import InvoiceItem
9
9
  from .mixins.crud import CRUDMixin
10
10
  from .mixins.recycle_bin import RecycleBinMixin
11
11
 
12
12
 
13
13
  class InvoiceMixin(
14
- CRUDMixin[Invoice, InvoiceCreate, InvoiceUpdate], RecycleBinMixin[Invoice]
14
+ CRUDMixin[Invoice, InvoiceCreate, InvoiceUpdate, InvoiceFilter],
15
+ RecycleBinMixin[Invoice],
15
16
  ):
16
17
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
17
18
  super().__init__()
@@ -4,11 +4,18 @@ All methods related to invoices
4
4
  import logging
5
5
 
6
6
  from ..core.client import EasyvereinClient
7
- from ..models.invoice_item import InvoiceItem, InvoiceItemCreate, InvoiceItemUpdate
7
+ from ..models.invoice_item import (
8
+ InvoiceItem,
9
+ InvoiceItemCreate,
10
+ InvoiceItemFilter,
11
+ InvoiceItemUpdate,
12
+ )
8
13
  from .mixins.crud import CRUDMixin
9
14
 
10
15
 
11
- class InvoiceItemMixin(CRUDMixin[InvoiceItem, InvoiceItemCreate, InvoiceItemUpdate]):
16
+ class InvoiceItemMixin(
17
+ CRUDMixin[InvoiceItem, InvoiceItemCreate, InvoiceItemUpdate, InvoiceItemFilter]
18
+ ):
12
19
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
13
20
  self.endpoint_name = "invoice-item"
14
21
  self.return_type = InvoiceItem
@@ -4,13 +4,13 @@ All methods related to invoices
4
4
  import logging
5
5
 
6
6
  from ..core.client import EasyvereinClient
7
- from ..models.member import Member, MemberCreate, MemberUpdate
7
+ from ..models.member import Member, MemberCreate, MemberFilter, MemberUpdate
8
8
  from .mixins.crud import CRUDMixin
9
9
  from .mixins.recycle_bin import RecycleBinMixin
10
10
 
11
11
 
12
12
  class MemberMixin(
13
- CRUDMixin[Member, MemberCreate, MemberUpdate], RecycleBinMixin[Member]
13
+ CRUDMixin[Member, MemberCreate, MemberUpdate, MemberFilter], RecycleBinMixin[Member]
14
14
  ):
15
15
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
16
16
  self.endpoint_name = "member"
@@ -6,12 +6,18 @@ import logging
6
6
  from ..core.client import EasyvereinClient
7
7
  from ..core.protocol import IsEVClientProtocol
8
8
  from ..models import MemberCustomField, MemberCustomFieldCreate, MemberCustomFieldUpdate
9
+ from ..models.member_custom_field import MemberCustomFieldFilter
9
10
  from .mixins.crud import CRUDMixin
10
11
  from .mixins.recycle_bin import RecycleBinMixin
11
12
 
12
13
 
13
14
  class MemberCustomFieldMixin(
14
- CRUDMixin[MemberCustomField, MemberCustomFieldCreate, MemberCustomFieldUpdate],
15
+ CRUDMixin[
16
+ MemberCustomField,
17
+ MemberCustomFieldCreate,
18
+ MemberCustomFieldUpdate,
19
+ MemberCustomFieldFilter,
20
+ ],
15
21
  RecycleBinMixin[MemberCustomField],
16
22
  ):
17
23
  def __init__(self, client: EasyvereinClient, logger: logging.Logger):
@@ -11,28 +11,46 @@ from easyverein.core.protocol import IsEVClientProtocol
11
11
  ModelType = TypeVar("ModelType", bound=BaseModel)
12
12
  CreateModelType = TypeVar("CreateModelType", bound=BaseModel)
13
13
  UpdateModelType = TypeVar("UpdateModelType", bound=BaseModel)
14
+ FilterType = TypeVar("FilterType", bound=BaseModel)
14
15
 
15
16
 
16
- class CRUDMixin(Generic[ModelType, CreateModelType, UpdateModelType]):
17
+ class CRUDMixin(Generic[ModelType, CreateModelType, UpdateModelType, FilterType]):
17
18
  def get(
18
- self: IsEVClientProtocol, query: str = None, limit: int = 10
19
- ) -> list[ModelType]:
19
+ self: IsEVClientProtocol,
20
+ query: str = None,
21
+ search: FilterType = None,
22
+ limit: int = 10,
23
+ page: int = 1,
24
+ ) -> tuple[list[ModelType], int]:
20
25
  """
21
26
  Fetches a single page of a given page size. The page size is defined by the `limit` parameter
22
27
  with an API sided upper limit of 100.
23
28
 
29
+ Returns a tuple, where the first element is the returned objects and the second is the total count.
30
+
24
31
  Args:
25
32
  query: Query to use with API. Refer to the EV API help for more information on how to use queries
33
+ search: Filter to use with API. Refer to the EV API help for more information on how to use filters
26
34
  limit: Defines how many resources to return.
35
+ page: Deinfines which page to return. Defaults to 1, which is the first page.
27
36
  """
28
37
  self.logger.info(f"Fetching selected {self.endpoint_name} objects from API")
29
38
 
30
- url = self.c.get_url(f"/{self.endpoint_name}", {"limit": limit, "query": query})
39
+ url_params = {"limit": limit, "query": query, "page": page}
40
+ if search:
41
+ url_params |= search.model_dump(exclude_unset=True, exclude_defaults=True)
42
+
43
+ self.logger.debug(f"Computed URL params for this request: {url_params}")
44
+
45
+ url = self.c.get_url(f"/{self.endpoint_name}", url_params)
31
46
 
32
47
  return self.c.fetch(url, self.return_type)
33
48
 
34
49
  def get_all(
35
- self: IsEVClientProtocol, query: str = None, limit_per_page: int = 10
50
+ self: IsEVClientProtocol,
51
+ query: str = None,
52
+ search: FilterType = None,
53
+ limit_per_page: int = 10,
36
54
  ) -> list[ModelType]:
37
55
  """
38
56
  Convenient method that fetches all objects from the EV API, abstracting away the need to handle pagination.
@@ -43,13 +61,16 @@ class CRUDMixin(Generic[ModelType, CreateModelType, UpdateModelType]):
43
61
  Args:
44
62
  query: Query to use with API. Defaults to None. Refer to the EV API help for more
45
63
  information on how to use queries
64
+ search: Filter to use with API. Refer to the EV API help for more information on how to use filters
46
65
  limit_per_page: Defines how many resources to return. Defaults to 10.
47
66
  """
48
67
  self.logger.info(f"Fetching selected {self.endpoint_name} objects from API")
49
68
 
50
- url = self.c.get_url(
51
- f"/{self.endpoint_name}", {"limit": limit_per_page, "query": query}
52
- )
69
+ url_params = {"limit": limit_per_page, "query": query}
70
+ if search:
71
+ url_params |= search.model_dump(exclude_unset=True, exclude_defaults=True)
72
+
73
+ url = self.c.get_url(f"/{self.endpoint_name}", url_params)
53
74
 
54
75
  return self.c.fetch_paginated(url, self.return_type, limit_per_page)
55
76
 
@@ -8,7 +8,7 @@ ModelType = TypeVar("ModelType", bound=BaseModel)
8
8
 
9
9
 
10
10
  class RecycleBinMixin(Generic[ModelType]):
11
- def get_deleted(self: IsEVClientProtocol) -> list[ModelType]:
11
+ def get_deleted(self: IsEVClientProtocol) -> tuple[list[ModelType], int]:
12
12
  """
13
13
  Fetches all deleted resources from the recycle bin and returns a list.
14
14
  """
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-easyverein"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  description = "Python library to interact with the EasyVerein API"
5
5
  authors = ["Daniel Herrmann <daniel.herrmann1@gmail.com>"]
6
6
  readme = "README.md"
@@ -1,8 +0,0 @@
1
- """
2
- Middleware for FastAPI that supports authenticating users against Keycloak
3
- """
4
-
5
- __version__ = "0.0.1"
6
-
7
- # Export EasyVerein API directly
8
- from .api import EasyvereinAPI # noqa: F401