Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ When saying CRUD, it means the library supports various methods to **C**reate, *
**D**elete objects. See the API reference for details on supported CRUD operations.

* `booking`: CRUD, Bulk Create and Update, Soft-Delete
* `booking-project`: CRUD, Soft-Delete
* `billing-account`: CRUD, Soft-Delete
* `contact-details`: CRUD, Bulk Create and Update, Soft-Delete
* `contact-details-group`: CRUD, Soft-Delete
* `custom-fields`: CRUD, Soft-Delete
* `custom-fields/<id>/select-options`: CRUD
* `invoice`: CRUD, Bulk Create and Update, Soft-Delete, plus some convenience methods
Expand Down
33 changes: 33 additions & 0 deletions docs/api/endpoints/booking_project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
| API Endpoint | Namespace | Supported Generics |
|----------------------|---------------------------------------------|--------------------|
| `booking-project` | `evclient.booking_project.<method>` | CRUD, RecycleBin |

## Additional parameters

None

## Generic Model Mappings

| Generic Model | BookingProject Model |
|-------------------|------------------------|
| `ModelType` | `BookingProject` |
| `CreateModelType` | `BookingProjectCreate` |
| `UpdateModelType` | `BookingProjectUpdate` |

## Additional Methods

::: easyverein.modules.booking_project.BookingProjectMixin
options:
inherited_members: false
show_signature: true
show_signature_annotations: true
show_root_heading: false
show_bases: false
show_root_toc_entry: false
separate_signature: true
heading_level: 4
filters:
- "!^c$"
- "!^logger$"
- "!^endpoint_name"
- "!^return_type"
33 changes: 33 additions & 0 deletions docs/api/endpoints/contact_details_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
| API Endpoint | Namespace | Supported Generics |
|---------------------------|---------------------------------------------------|--------------------|
| `contact-details-group` | `evclient.contact_details_group.<method>` | CRUD, RecycleBin |

## Additional parameters

None

## Generic Model Mappings

| Generic Model | ContactDetailsGroup Model |
|-------------------|-----------------------------|
| `ModelType` | `ContactDetailsGroup` |
| `CreateModelType` | `ContactDetailsGroupCreate` |
| `UpdateModelType` | `ContactDetailsGroupUpdate` |

## Additional Methods

::: easyverein.modules.contact_details_group.ContactDetailsGroupMixin
options:
inherited_members: false
show_signature: true
show_signature_annotations: true
show_root_heading: false
show_bases: false
show_root_toc_entry: false
separate_signature: true
heading_level: 4
filters:
- "!^c$"
- "!^logger$"
- "!^endpoint_name"
- "!^return_type"
4 changes: 4 additions & 0 deletions docs/api/recycle_bin.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ with soft-deleted resources.
Note that not all endpoints support the soft-delete pattern. Using this Client, only the following
endpoints are supported for now:

- booking
- booking-project
- billing-account
- invoice
- member
- member-groups
- contact-details
- contact-details-group
- custom-field

Please refer to the offical API documentation for a full list endpoints supporting soft-delete.
Expand Down
13 changes: 8 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,16 @@ Not all endpoints offered by the EasyVerein API are supported. For now, only the
When saying CRUD, it means the library supports various methods to **C**reate, **R**ead, **U**pdate and **D**elete objects. See the API
reference for details on supported CRUD operations.

* `booking`: CRUD, Soft-Delete
* `billing_account`: CRUD, Soft-Delete
* `contact-details`: CRUD, Soft-Delete
* `booking`: CRUD, Bulk Create and Update, Soft-Delete
* `booking-project`: CRUD, Soft-Delete
* `billing-account`: CRUD, Soft-Delete
* `contact-details`: CRUD, Bulk Create and Update, Soft-Delete
* `contact-details-group`: CRUD, Soft-Delete
* `custom-fields`: CRUD, Soft-Delete
* `invoice`: CRUD, Soft-Delete, plus some convenience methods
* `custom-fields/<id>/select-options`: CRUD
* `invoice`: CRUD, Bulk Create and Update, Soft-Delete, plus some convenience methods
* `invoice-item`: CRUD
* `member`: CRUD, Soft-Delete
* `member`: CRUD, Bulk Create and Update, Soft-Delete
* `member-groups`: CRUD, Soft-Delete
* `member/<id>/custom-fields`: CRUD, plus some convenience methods
* `member/<id>/member-groups`: CRUD, plus some convenience methods
Expand Down
10 changes: 10 additions & 0 deletions docs/models/booking_project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
::: easyverein.models.booking_project.BookingProjectBase
options:
show_root_heading: false
heading_level: 2
show_signature_annotations: true
show_if_no_docstring: true
show_category_heading: false
show_docstring_modules: false
show_root_toc_entry: false
members: True
10 changes: 10 additions & 0 deletions docs/models/contact_details_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
::: easyverein.models.contact_details_group.ContactDetailsGroupBase
options:
show_root_heading: false
heading_level: 2
show_signature_annotations: true
show_if_no_docstring: true
show_category_heading: false
show_docstring_modules: false
show_root_toc_entry: false
members: True
5 changes: 5 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,14 @@ are only supported on endpoints which make use of the soft-delete pattern.
!!! info "Endpoints supporting soft-delete"
As of today, only the following endpoints are implemented by this library and support the soft-delete pattern:

- booking
- booking-project
- billing-account
- invoice
- member
- member-group
- contact-details
- contact-details-group
- custom-field

For these endpoints, three additional methods are provided. Refer to the API documentation for details.
Expand Down
4 changes: 4 additions & 0 deletions easyverein/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from .core.responses import BearerToken
from .modules.billing_account import BillingAccountMixin
from .modules.booking import BookingMixin
from .modules.booking_project import BookingProjectMixin
from .modules.contact_details import ContactDetailsMixin
from .modules.contact_details_group import ContactDetailsGroupMixin
from .modules.custom_field import CustomFieldMixin
from .modules.invoice import InvoiceMixin
from .modules.invoice_item import InvoiceItemMixin
Expand Down Expand Up @@ -60,8 +62,10 @@ def __init__(

# Add methods
self.booking = BookingMixin(self.c, self.logger)
self.booking_project = BookingProjectMixin(self.c, self.logger)
self.billing_account = BillingAccountMixin(self.c, self.logger)
self.contact_details = ContactDetailsMixin(self.c, self.logger)
self.contact_details_group = ContactDetailsGroupMixin(self.c, self.logger)
self.custom_field = CustomFieldMixin(self.c, self.logger)
self.invoice = InvoiceMixin(self.c, self.logger)
self.invoice_item = InvoiceItemMixin(self.c, self.logger)
Expand Down
14 changes: 6 additions & 8 deletions easyverein/core/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pathlib import Path
from time import sleep
from typing import TYPE_CHECKING, Any
from urllib.parse import urlencode

import requests
from pydantic import BaseModel
Expand Down Expand Up @@ -67,14 +68,11 @@ def get_url(self, path: str, url_params: dict | None = None) -> str:
self.logger.debug(f"Base URL is {url}")

if url_params:
for key, value in url_params.items():
if value in {None, ""}:
continue
self.logger.debug(f"Adding {key}={value} path parameter to URL")
if "?" not in url:
url += f"?{key}={value}"
else:
url += f"&{key}={value}"
params_ = {key: value for key, value in url_params.items() if value not in {None, ""}}
if params_:
self.logger.debug(f"Adding URL parameters: {params_}")
first_separator = "&" if "?" in url else "?"
url += first_separator + urlencode(params_)

self.logger.debug(f"Final constructed URL is {url}")

Expand Down
14 changes: 14 additions & 0 deletions easyverein/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# noqa: F401
from .booking import Booking, BookingCreate, BookingFilter, BookingUpdate
from .booking_project import (
BookingProject,
BookingProjectCreate,
BookingProjectFilter,
BookingProjectUpdate,
)
from .contact_details import (
ContactDetails,
ContactDetailsCreate,
ContactDetailsFilter,
ContactDetailsUpdate,
)
from .contact_details_group import (
ContactDetailsGroup,
ContactDetailsGroupCreate,
ContactDetailsGroupFilter,
ContactDetailsGroupUpdate,
)
from .custom_field import (
CustomField,
CustomFieldCreate,
Expand Down Expand Up @@ -41,7 +53,9 @@
)

Booking.model_rebuild()
BookingProject.model_rebuild()
ContactDetails.model_rebuild()
ContactDetailsGroup.model_rebuild()
CustomField.model_rebuild()
CustomFieldSelectOption.model_rebuild()
Invoice.model_rebuild()
Expand Down
4 changes: 2 additions & 2 deletions easyverein/models/billing_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class BillingAccount(BillingAccountBase, EmptyStringsToNone):

skr: str | None = None
accountingPlans: list[EasyVereinReference] | None = None
numberLength: PositiveIntWithZero
linkedBookings: PositiveIntWithZero
numberLength: PositiveIntWithZero | None = None
linkedBookings: PositiveIntWithZero | None = None


class BillingAccountCreate(
Expand Down
10 changes: 7 additions & 3 deletions easyverein/models/booking.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class BookingBase(EasyVereinBase):
counterpartIban: str | None = None
counterpartBic: str | None = None
twingleDonation: bool | None = None
bookingProject: str | None = None
bookingProject: EasyVereinReference | BookingProject | None = None
sphere: Sphere | None = None
relatedInvoice: list[EasyVereinReference] | None = None
relatedInvoice: list[EasyVereinReference] | list[Invoice] | None = None


class Booking(BookingBase, EmptyStringsToNone):
Expand All @@ -47,12 +47,14 @@ class Booking(BookingBase, EmptyStringsToNone):

class BookingCreate(
BookingBase,
required_mixin(["receiver", "date"]), # type: ignore
required_mixin(["date"]), # type: ignore
):
"""
Pydantic model representing a Booking
"""

receiver: str | None = ""


class BookingUpdate(BookingBase):
"""
Expand Down Expand Up @@ -100,3 +102,5 @@ class BookingFilter(BaseModel):


from .billing_account import BillingAccount # noqa: E402
from .booking_project import BookingProject # noqa: E402
from .invoice import Invoice # noqa: E402
57 changes: 57 additions & 0 deletions easyverein/models/booking_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from pydantic import BaseModel, PositiveInt

from easyverein.core.types import FilterIntList, HexColor
from easyverein.models.base import EasyVereinBase
from easyverein.models.mixins.empty_strings_mixin import EmptyStringsToNone

from .mixins.required_attributes import required_mixin


class BookingProjectBase(EasyVereinBase):
"""
| Representative Model Class | Update Model Class | Create Model Class |
| --- | --- | --- |
| `BookingProject` | `BookingProjectUpdate` | `BookingProjectCreate` |
"""

name: str | None = None
short: str | None = None
color: HexColor = None
budget: float | None = None
completed: bool | None = None
projectCostCentre: str | None = None


class BookingProject(BookingProjectBase, EmptyStringsToNone):
"""
Pydantic model for booking project
"""

pass


class BookingProjectUpdate(BookingProjectBase):
"""
Pydantic model used to update booking project
"""


class BookingProjectCreate(BookingProjectUpdate, required_mixin(["name", "short"])): # type: ignore
"""
Pydantic model for creating new booking project
"""


class BookingProjectFilter(BaseModel):
"""
Pydantic model used to filter booking project
"""

id__in: FilterIntList | None = None
budget__lt: PositiveInt | None = None
budget__gt: PositiveInt | None = None
completed: bool | None = None
name: str | None = None
short: str | None = None
ordering: str | None = None
search: str | None = None
10 changes: 8 additions & 2 deletions easyverein/models/contact_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from pydantic import BaseModel, EmailStr, Field

from ..core.types import Date, FilterIntList
from ..core.types import Date, EasyVereinReference, FilterIntList
from .base import EasyVereinBase
from .mixins.empty_strings_mixin import EmptyStringsToNone
from .mixins.required_attributes import required_mixin
Expand All @@ -25,6 +25,7 @@ class ContactDetailsBase(EasyVereinBase):
are required to have a contact details object linked.
"""

contactDetailsGroups: list[EasyVereinReference | ContactDetailsGroup] | None = Field(default=None)
isCompany: bool | None = Field(default=None, alias="_isCompany")
"""Alias for `_isCompany` field. See [Pydantic Models](../usage.md#pydantic-models) for details."""
salutation: Literal["", "Herr", "Frau"] | None = None
Expand Down Expand Up @@ -86,6 +87,7 @@ class ContactDetailsBase(EasyVereinBase):
- 3: cash
- 4: other
"""
# TODO: Actual get method returns a string, f.e. "Lastschrift" (in german)
datevAccountNumber: int | None = None
# TODO: Refine once available from API description
copiedFromParent: Any | None = Field(default=None, alias="_copiedFromParent")
Expand Down Expand Up @@ -123,7 +125,7 @@ class ContactDetails(ContactDetailsBase, EmptyStringsToNone):
Pydantic model for contact details
"""

pass
member: EasyVereinReference | Member | None = None


class ContactDetailsUpdate(ContactDetailsBase):
Expand Down Expand Up @@ -167,3 +169,7 @@ class ContactDetailsFilter(BaseModel):
hasCopy: bool | None = None
ordering: str | None = None
search: str | None = None


from .contact_details_group import ContactDetailsGroup
from .member import Member
Loading
Loading