Source code for people.models.membership

from onegov.core.orm import Base
from onegov.core.orm.mixins import ContentMixin
from onegov.core.orm.mixins import TimestampMixin
from onegov.core.orm.mixins import UTCPublicationMixin
from onegov.core.orm.types import UUID
from onegov.search import ORMSearchable
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Text
from sqlalchemy.orm import object_session
from sqlalchemy.orm import relationship
from uuid import uuid4


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    import uuid
    from collections.abc import Collection
    from sqlalchemy.orm import Query
    from typing import Self
    from .agency import Agency
    from .person import Person


[docs] class AgencyMembership(Base, ContentMixin, TimestampMixin, ORMSearchable, UTCPublicationMixin): """ A membership to an agency. """
[docs] __tablename__ = 'agency_memberships'
#: the type of the item, this can be used to create custom polymorphic #: subclasses of this class. See #: `<https://docs.sqlalchemy.org/en/improve_toc/\ #: orm/extensions/declarative/inheritance.html>`_.
[docs] type: 'Column[str]' = Column( Text, nullable=False, default=lambda: 'generic' )
[docs] __mapper_args__ = { 'polymorphic_on': type, 'polymorphic_identity': 'generic', }
[docs] es_public = True
[docs] es_properties = { 'title': {'type': 'text'}, }
#: the unique id, part of the url
[docs] id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] primary_key=True, default=uuid4 )
#: the id of the agency
[docs] agency_id: 'Column[int]' = Column( Integer, ForeignKey('agencies.id'), nullable=False )
#: the related agency (which may have any number of memberships)
[docs] agency: 'relationship[Agency]' = relationship( 'Agency', back_populates='memberships' )
#: the id of the person
[docs] person_id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] ForeignKey('people.id'), nullable=False )
#: the related person (which may have any number of memberships)
[docs] person: 'relationship[Person]' = relationship( 'Person', back_populates='memberships', )
#: the position of the membership within the agency
[docs] order_within_agency: 'Column[int]' = Column(Integer, nullable=False)
#: the position of the membership within all memberships of a person
[docs] order_within_person: 'Column[int]' = Column(Integer, nullable=False)
#: describes the membership
[docs] title: 'Column[str]' = Column(Text, nullable=False)
#: when the membership started
[docs] since: 'Column[str | None]' = Column(Text, nullable=True)
@property
[docs] def siblings_by_agency(self) -> 'Query[Self]': """ Returns a query that includes all siblings by agency, including the item itself ordered by `order_within_agency`. """ # FIXME: This has the same problem as AdjacencyList.siblings cls = self.__class__ query = object_session(self).query(cls) query = query.order_by(cls.order_within_agency) query = query.filter(cls.agency == self.agency) return query
@property
[docs] def siblings_by_person(self) -> 'Query[Self]': """ Returns a query that includes all siblings by person, including the item itself ordered by `order_within_person`. """ # FIXME: This has the same problem as AdjacencyList.siblings cls = self.__class__ query = object_session(self).query(cls) query = query.order_by(cls.order_within_person) query = query.filter(cls.person == self.person) return query
[docs] def vcard(self, exclude: 'Collection[str] | None ' = None) -> str: """ Returns the person as vCard (3.0). Allows to specify the included attributes, provides a reasonable default if none are specified. Always includes the first and last name. """ if not self.person: return '' result = self.person.vcard_object(exclude, include_memberships=False) line = result.add('org') line.value = [f'{self.agency.title}, {self.title}'] line.charset_param = 'utf-8' return result.serialize()